Repository: SINTEF/dlite (language: python)

Issue:
Fixed test_metamodel



Discussion / hints:

Fix patch:
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
index 379714664..9a259855f 100644
--- a/.devcontainer/devcontainer.json
+++ b/.devcontainer/devcontainer.json
@@ -10,7 +10,7 @@
 	"dockerFile": "..\\Dockerfile",
 
 	"build": {
-		"target": "dependencies"
+		"target": "build"
 	},
 
 	// Set *default* container specific settings.json values on container create.
diff --git a/src/dlite-entity.c b/src/dlite-entity.c
index ef9dfdcd5..0283524b4 100644
--- a/src/dlite-entity.c
+++ b/src/dlite-entity.c
@@ -2415,7 +2415,7 @@ const char *dlite_metamodel_missing_value(const DLiteMetaModel *model)
   for (i=0; i < model->meta->_nproperties; i++) {
     DLiteProperty *p = model->meta->_properties + i;
     if (strcmp(p->name, "dimensions") == 0) {
-      if (!model->dims) return p->name;
+      continue;
     } else if (strcmp(p->name, "properties") == 0) {
       if (!model->props) return p->name;
     } else if (strcmp(p->name, "relations") == 0) {
@@ -2486,7 +2486,6 @@ DLiteMeta *dlite_meta_create_from_metamodel(DLiteMetaModel *model)
   if (!(meta = (DLiteMeta *)dlite_instance_create(model->meta,
                                                   model->dimvalues,
                                                   model->uri))) goto fail;
-  if (dlite_meta_init(meta)) goto fail;
   if (model->iri && !(meta->iri = strdup(model->iri)))
     FAIL("allocation failure");
 
@@ -2496,14 +2495,21 @@ DLiteMeta *dlite_meta_create_from_metamodel(DLiteMetaModel *model)
     DLiteProperty *p = model->meta->_properties + i;
     size_t *dims = (p->ndims) ? DLITE_PROP_DIMS(meta, i) : NULL;
 
-    if (!(src = dlite_metamodel_get_property(model, p->name))) goto fail;
-    if (!(dest = dlite_instance_get_property_by_index((DLiteInstance *)meta,
-                                                      i))) goto fail;
-    if (dlite_type_ndcast(p->ndims,
-                          dest, p->type, p->size, dims, NULL,
-                          src, p->type, p->size, dims, NULL,
-                          NULL)) goto fail;
+    src = dlite_metamodel_get_property(model, p->name);
+    dest = dlite_instance_get_property_by_index((DLiteInstance *)meta, i);
+    if ((src == NULL) && (dest == NULL)) {
+      continue;
+    }
+    else if ((src != NULL) && (dest != NULL)) {
+      if (dlite_type_ndcast(p->ndims,
+                            dest, p->type, p->size, dims, NULL,
+                            src, p->type, p->size, dims, NULL,
+                            NULL)) goto fail;
+    } else {
+      goto fail;
+    }
   }
+  if (dlite_meta_init(meta)) goto fail;
   retval = meta;
  fail:
   if (name) free(name);
diff --git a/tools/templates/fortran-module.txt b/tools/templates/fortran-module.txt
index 7f1b1b1d4..2fe43174e 100644
--- a/tools/templates/fortran-module.txt
+++ b/tools/templates/fortran-module.txt
@@ -8,7 +8,7 @@
 ! This file instantiate a hardcoded instance of metadata {meta.name}.
 !
 !
-! Fortran interface to Person entity from Person.json
+! Fortran interface to {name} entity from {name}.json
 !
 {have_fixstring_arr=0}\
 {list_properties:\
@@ -17,7 +17,6 @@
 {@endif}\
 }\
 
-
 module {name}
     USE iso_c_binding, only : c_ptr, c_int, c_char, c_null_char, c_size_t,    &
                               c_double, c_null_ptr, c_f_pointer, c_associated,&
@@ -61,8 +60,10 @@ module {name}
       module procedure readFromStorage
       ! create a {name} and allocate the arrays (type of dimensions: integer(4))
       module procedure create32
+{@if:{_ndimensions}>0}
       ! create a {name} and allocate the arrays (type of dimensions: integer(8))
       module procedure create64
+{@endif}      
     END INTERFACE T{name}
 
   contains
@@ -91,7 +92,7 @@ module {name}
 {list_dimensions:{@4}{name%c}%{dim.name} = {dim.name}\n}
 {list_properties:{@4}! {prop.name}\n{@if:{prop.ndims}!0}{@4}allocate({name%c}%{prop.name}({prop.dims:{dim.name}{,}\.}))\n{@endif}\ }
   end function create32
-
+{@if:{_ndimensions}>0}
   function create64({list_dimensions:{dim.name}{, }\.}) result({name%c})
     implicit none
     type(T{name}) :: {name%c}
@@ -102,12 +103,12 @@ module {name}
 {list_dimensions:{@4}{name%c}%{dim.name} = {dim.name}\n}
 {list_properties:{@4}! {prop.name}\n{@if:{prop.ndims}!0}{@4}allocate({name%c}%{prop.name}({prop.dims:{dim.name}{,}\.}))\n{@endif}\ }
   end function create64
-
+{@endif}
   subroutine readFromInstance({name%c}, instance)
     class(T{name})                        :: {name%c}
     type(DLiteInstance), intent(in)       :: instance
-    type(c_ptr)                           :: cptr
-    integer(8), dimension(*), allocatable :: dims(:)
+    {@if:{_ndimensions}>0}{@3}type(c_ptr){@42}:: cptr{@endif}
+    {@if:{_ndimensions}>0}{@3}integer(8), dimension(*), allocatable :: dims(:){@endif}
 {@if:{have_fixstring_arr}\.}\
     integer(8)                            :: strlen, nstring, i
 {@endif}\
@@ -163,8 +164,9 @@ module {name}
   function writeToInstance({name%c}) result(instance)
     class(T{name})                        :: {name%c}
     type(DLiteInstance)                   :: instance
-    type(c_ptr)                           :: cptr
-    integer(8), dimension(*), allocatable :: dims(:)
+    {@if:{_ndimensions}>0}{@3}type(c_ptr){@42}:: cptr{@endif}
+    {@if:{_ndimensions}>0}{@3}integer(8), dimension(*), allocatable :: dims(:){@endif}
+    integer(8), dimension({_ndimensions}) :: dimensions    
 {list_properties:\
 {@if:{prop.typeno}=5}\
 {@4}! {prop.isoctype} {@42}:: {prop.name}\n\
@@ -176,10 +178,11 @@ module {name}
     if ({name%c}%check()) then
       instance = {name%c}%instance
     else
+      {@if:{_ndimensions}>0}{@8}dimensions = [ {list_dimensions:{name%c}%{dim.name}{, }\.} ]{@endif}
       instance = DLiteInstance(&
                     '{_uri}', &
                     {_ndimensions}, &
-                    [{list_dimensions:{name%c}%{dim.name}{, }\.}], &
+                    dimensions, &
                     {name%c}%uuid)
       {name%c}%instance = instance
     endif


Test patch:
diff --git a/bindings/fortran/tests/Animal.json b/bindings/fortran/tests/Animal.json
new file mode 100644
index 000000000..be664ba67
--- /dev/null
+++ b/bindings/fortran/tests/Animal.json
@@ -0,0 +1,21 @@
+{
+    "name": "Animal",
+    "version": "0.1",
+    "namespace": "http://meta.sintef.no",
+    "meta": "http://meta.sintef.no/0.3/EntitySchema",
+    "description": "Define a metadata without dimension.",
+    "dimensions": [
+    ],
+    "properties": [
+      {
+        "name": "name",
+        "type": "string45",
+        "description": "Trivial name."
+      },
+      {
+        "name": "young",
+        "type": "string45",
+        "description": "Specific name for young animal."
+      }
+    ]
+}
diff --git a/bindings/fortran/tests/CMakeLists.txt b/bindings/fortran/tests/CMakeLists.txt
index 9a206594c..1b09af437 100644
--- a/bindings/fortran/tests/CMakeLists.txt
+++ b/bindings/fortran/tests/CMakeLists.txt
@@ -5,46 +5,34 @@ include(dliteCodeGen)
 
 add_compile_options("-DDLITE_ROOT=${DLITE_ROOT}")
 
-dlite_codegen(
-  ${CMAKE_CURRENT_BINARY_DIR}/Person.f90
-  fortran-module
-  json://${CMAKE_CURRENT_SOURCE_DIR}/Person.json?mode=r
-  ENV_OPTIONS --build
-  --build-root
-  )
-
-dlite_codegen(
-  ${CMAKE_CURRENT_BINARY_DIR}/Scan3D.f90
-  fortran-module
-  json://${CMAKE_CURRENT_SOURCE_DIR}/Scan3D.json?mode=r
-  ENV_OPTIONS --build
-  --build-root
-  )
+set(metadata
+  Person
+  Scan3D
+  Animal
+)
+foreach(name ${metadata})
+  dlite_codegen(
+    ${CMAKE_CURRENT_BINARY_DIR}/${name}.f90
+    fortran-module
+    json://${CMAKE_CURRENT_SOURCE_DIR}/${name}.json?mode=r
+    ENV_OPTIONS --build
+    --build-root
+    )
+  add_library(${name} ${CMAKE_CURRENT_BINARY_DIR}/${name}.f90)
+  target_link_libraries(${name}
+    dlite
+    dlite-utils
+    dlite-fortran
+    )
+  target_include_directories(${name} PRIVATE
+    ${dlite-bindings-fortran_BINARY_DIR}
+    ${CMAKE_CURRENT_BINARY_DIR}
+    )
+endforeach()
 
 set(tests
   test_person
-  )
-
-add_library(Person ${CMAKE_CURRENT_BINARY_DIR}/Person.f90)
-target_link_libraries(Person
-  dlite
-  dlite-utils
-  dlite-fortran
-  )
-target_include_directories(Person PRIVATE
-  ${dlite-bindings-fortran_BINARY_DIR}
-  ${CMAKE_CURRENT_BINARY_DIR}
-  )
-
-add_library(Scan3D ${CMAKE_CURRENT_BINARY_DIR}/Scan3D.f90)
-target_link_libraries(Scan3D
-  dlite
-  dlite-utils
-  dlite-fortran
-  )
-target_include_directories(Scan3D PRIVATE
-  ${dlite-bindings-fortran_BINARY_DIR}
-  ${CMAKE_CURRENT_BINARY_DIR}
+  test_animal
   )
 
 foreach(test ${tests})
@@ -55,6 +43,7 @@ foreach(test ${tests})
     dlite-fortran
     Person
     Scan3D
+    Animal
     )
   target_include_directories(${test} PRIVATE
     ${dlite-bindings-fortran_BINARY_DIR}
diff --git a/bindings/fortran/tests/Person.json b/bindings/fortran/tests/Person.json
index d9e004406..516cba047 100644
--- a/bindings/fortran/tests/Person.json
+++ b/bindings/fortran/tests/Person.json
@@ -45,4 +45,4 @@
     }
   ],
   "dataname": "http://meta.sintef.no/0.2/Person"
-}
\ No newline at end of file
+}
diff --git a/bindings/fortran/tests/Scan3D.json b/bindings/fortran/tests/Scan3D.json
index 4565013c0..6606ca01d 100644
--- a/bindings/fortran/tests/Scan3D.json
+++ b/bindings/fortran/tests/Scan3D.json
@@ -28,4 +28,4 @@
         "description": "Point cloud."
         }
     ]
-}
\ No newline at end of file
+}
diff --git a/bindings/fortran/tests/test_animal.f90 b/bindings/fortran/tests/test_animal.f90
new file mode 100644
index 000000000..b033d9d8b
--- /dev/null
+++ b/bindings/fortran/tests/test_animal.f90
@@ -0,0 +1,33 @@
+! You must set environment variable DLITE_STORAGES='*.json' and run
+! this test from the same directory as this file
+
+program ftest_animal
+
+  use iso_c_binding
+  use DLite
+  ! use dlite_config, only: dlite_fortran_test_dir
+  use Animal
+
+  implicit none
+
+  type(TAnimal)      :: dog
+  type(TAnimal)      :: cat
+  integer            :: status
+
+  print *, "test_animal.f90: create animals"
+
+  dog = TAnimal()
+  dog%name = 'dog'
+  dog%young = 'puppy'
+
+  cat = TAnimal()
+  cat%name = 'cat'
+  cat%young = 'kitten'
+
+  status = dog%writeToURL("json://animals.json?mode=w")
+  status = cat%writeToURL("json://animals.json?mode=append")
+
+  status = dog%destroy()
+  status = cat%destroy()
+
+end program ftest_animal
diff --git a/src/tests/test_entity.c b/src/tests/test_entity.c
index bbfd6a820..6b331a27b 100644
--- a/src/tests/test_entity.c
+++ b/src/tests/test_entity.c
@@ -224,13 +224,13 @@ MU_TEST(test_meta_save)
 {
   DLiteStorage *s;
 #ifdef WITH_JSON
-  mu_check((s = dlite_storage_open("json", "SEntity.json", "mode=w;meta=1")));
+  mu_check((s = dlite_storage_open("json", "MyEntityX.json", "mode=w;meta=1")));
   mu_check(dlite_meta_save(s, entity) == 0);
   mu_check(dlite_storage_close(s) == 0);
 #endif
 
 #ifdef WITH_JSON
-  mu_check((s = dlite_storage_open("json", "SEntity2.json", "mode=w;meta=0")));
+  mu_check((s = dlite_storage_open("json", "MyEntityX2.json", "mode=w;meta=0")));
   mu_check(dlite_meta_save(s, entity) == 0);
   mu_check(dlite_storage_close(s) == 0);
 #endif
@@ -242,22 +242,22 @@ MU_TEST(test_meta_load)
   DLiteStorage *s;
   DLiteMeta *e, *e2;
 #ifdef WITH_JSON
-  mu_check((s = dlite_storage_open("json", "SEntity.json", "mode=r")));
+  mu_check((s = dlite_storage_open("json", "MyEntityX.json", "mode=r")));
   mu_check((e = dlite_meta_load(s, uri)));
   mu_check(dlite_storage_close(s) == 0);
   mu_assert_int_eq(3, entity->_refcount);  /* refs: global+store+e */
 
-  mu_check((s = dlite_storage_open("json", "SEntity2.json", "mode=r")));
+  mu_check((s = dlite_storage_open("json", "MyEntityX2.json", "mode=r")));
   mu_check((e2 = dlite_meta_load(s, uri)));
   mu_check(dlite_storage_close(s) == 0);
   mu_assert_int_eq(4, entity->_refcount);  /* refs: global+store+e+e2 */
 
-  mu_check((s = dlite_storage_open("json", "SEntity3.json", "mode=w;meta=1")));
+  mu_check((s = dlite_storage_open("json", "MyEntityX3.json", "mode=w;meta=1")));
   mu_check(dlite_meta_save(s, e) == 0);
   mu_check(dlite_storage_close(s) == 0);
   mu_assert_int_eq(4, entity->_refcount);  /* refs: global+store+e+e2 */
 
-  mu_check((s = dlite_storage_open("json", "SEntity4.json", "mode=w;meta=1")));
+  mu_check((s = dlite_storage_open("json", "MyEntityX4.json", "mode=w;meta=1")));
   mu_check(dlite_meta_save(s, e2) == 0);
   mu_check(dlite_storage_close(s) == 0);
   mu_assert_int_eq(4, entity->_refcount);  /* refs: global+store+e+e2 */
diff --git a/src/tests/test_metamodel.c b/src/tests/test_metamodel.c
index 4ba39b76f..e7e4f2b51 100644
--- a/src/tests/test_metamodel.c
+++ b/src/tests/test_metamodel.c
@@ -7,6 +7,7 @@
 
 
 DLiteMetaModel *model;
+DLiteMetaModel *nodim;
 
 
 MU_TEST(test_metamodel_create)
@@ -14,12 +15,20 @@ MU_TEST(test_metamodel_create)
   model = dlite_metamodel_create("http://meta.sintef.no/0.1/Vehicle",
                                  DLITE_ENTITY_SCHEMA, NULL);
   mu_check(model);
+
+  nodim = dlite_metamodel_create("http://meta.sintef.no/1.0/NoDimension",
+                                 DLITE_ENTITY_SCHEMA, NULL);
+  mu_check(nodim);
+
 }
 
 MU_TEST(test_metamodel_add_value)
 {
   char *descr = "A vehicle like car, bike, etc...";
   mu_assert_int_eq(0, dlite_metamodel_add_string(model, "description", descr));
+
+  char *descr2 = "A metadata without dimension";
+  mu_assert_int_eq(0, dlite_metamodel_add_string(nodim, "description", descr2));
 }
 
 MU_TEST(test_metamodel_add_dimension)
@@ -40,21 +49,61 @@ MU_TEST(test_metamodel_add_property)
   mu_assert_int_eq(0, stat);
   stat = dlite_metamodel_add_property_dim(model, "checks", "nchecks");
   mu_assert_int_eq(0, stat);
+
+  stat = dlite_metamodel_add_property(nodim, "name", "string32", NULL, NULL,
+                                      "Name of the instance.");
+  mu_assert_int_eq(0, stat);
+  stat = dlite_metamodel_add_property(nodim, "value", "float", "mm", NULL,
+                                      "Value of the instance.");
+  mu_assert_int_eq(0, stat);
 }
 
 MU_TEST(test_metamodel_create_meta)
 {
+  int stat;
+
   DLiteMeta *meta = dlite_meta_create_from_metamodel(model);
   mu_check(meta);
   //dlite_instance_print((DLiteInstance *)meta);
   dlite_instance_save_url("json://Vehicle.json?mode=w&meta=yes",
                           (DLiteInstance *)meta);
+
+  size_t dims[] = {0};
+  DLiteInstance *vehicle = dlite_instance_create(meta, dims, NULL);
+  mu_check(vehicle);
+  char *brand = "Ford";
+  stat = dlite_instance_set_property(vehicle, "brand", brand);
+  mu_assert_int_eq(0, stat);
+  stat = dlite_instance_save_url("json://Ford.json?mode=w", vehicle);
+  mu_assert_int_eq(0, stat);
+  dlite_instance_decref(vehicle);
   dlite_meta_decref(meta);
+
+  DLiteMeta *meta2 = dlite_meta_create_from_metamodel(nodim);
+  mu_check(meta2);
+  //dlite_instance_print((DLiteInstance *)meta);
+  dlite_instance_save_url("json://NoDimension.json?mode=w&meta=yes",
+                          (DLiteInstance *)meta2);
+
+  DLiteInstance *inst = dlite_instance_create(meta2, NULL, NULL);
+  mu_check(inst);
+  char *name = "John";
+  stat = dlite_instance_set_property(inst, "name", name);
+  mu_assert_int_eq(0, stat);
+  float value = 33.0;
+  stat = dlite_instance_set_property(inst, "value", &value);
+  mu_assert_int_eq(0, stat);
+  stat = dlite_instance_save_url("json://JohnNoDim.json?mode=w", inst);
+  mu_assert_int_eq(0, stat);
+
+  dlite_instance_decref(inst);
+  dlite_meta_decref(meta2);
 }
 
 MU_TEST(test_metamodel_free)
 {
   dlite_metamodel_free(model);
+  dlite_metamodel_free(nodim);
 }