# ** header v3.0 # This file is a part of the CaosDB Project. # # Copyright (C) 2021 Indiscale GmbH <info@indiscale.com> # Copyright (C) 2021 Florian Spreckelsen <f.spreckelsen@indiscale.com> # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public # License along with this program. If not, see # <https://www.gnu.org/licenses/>. # # ** end header # using Test using CaosDB @testset "CaosDBUnitTests" begin @testset "TestUtility" begin if haskey(ENV, "SHELL") shell_var = ENV["SHELL"] else shell_var = "default" end @test CaosDB.Utility.get_env_fallback("SHELL", "default") == shell_var end @testset "TestExceptions" begin # In case of success, nothing is done @test CaosDB.Exceptions.evaluate_return_code(Cint(0)) == nothing # CaosDBExceptions are thrown for return codes > 0 @test_throws CaosDB.Exceptions.CaosDBException CaosDB.Exceptions.evaluate_return_code( Cint(14), ) @test_throws CaosDB.Exceptions.GenericCaosDBException CaosDB.Exceptions.evaluate_return_code( Cint(14), ) try CaosDB.Exceptions.evaluate_return_code(Cint(14)) # fail if this doesn't throw an error @test false catch e @test isa(e, CaosDB.Exceptions.GenericCaosDBException) @test e.code == 14 end # Return codes < 0 correspond to unfinished transactions and # we expect messages to be returned. @test CaosDB.Exceptions.evaluate_return_code(Cint(-1)) == nothing @test_logs ( :info, CaosDB.Exceptions.CaosDBMessage( "The transaction is currently being executed.", Cint(-1), ), ) CaosDB.Exceptions.evaluate_return_code(Cint(-1)) # Check whether client errors can be built correctly and # return the correct code (Change it if this ever changes in # libcaosdb) client_err = CaosDB.Exceptions.ClientException("Client error") @test client_err.msg == "Client error" @test client_err.code == 9999 end @testset "TestTransaction" begin # transactions can be generated from the default connection, # from a connection name, or from a connection object @test CaosDB.Transaction.create_transaction() != nothing @test CaosDB.Transaction.create_transaction("default") != nothing conn = CaosDB.Connection.get_connection() @test CaosDB.Transaction.create_transaction(conn) != nothing # Retrieval works by a single id, by a list of ids, or by querying trans1 = CaosDB.Transaction.create_transaction() @test CaosDB.Transaction.add_retrieve_by_id(trans1, "some_id") == nothing trans2 = CaosDB.Transaction.create_transaction() @test CaosDB.Transaction.add_retrieve_by_id(trans2, ["id1", "id2", "id3"]) == nothing trans3 = CaosDB.Transaction.create_transaction() @test CaosDB.Transaction.add_query(trans3, "FIND ENTITY WITH id=123") == nothing end @testset "TestEntity" begin ent_with_name = CaosDB.Entity.create_entity("TestEnt") @test CaosDB.Entity.get_name(ent_with_name) == "TestEnt" rt_with_name = CaosDB.Entity.create_recordtype("TestRT") @test CaosDB.Entity.get_name(rt_with_name) == "TestRT" @test CaosDB.Entity.get_role(rt_with_name) == "RECORD_TYPE" prop_with_name_and_unit = CaosDB.Entity.create_property_entity(name = "TestProp", unit = "m") @test CaosDB.Entity.get_name(prop_with_name_and_unit) == "TestProp" @test CaosDB.Entity.get_role(prop_with_name_and_unit) == "PROPERTY" @test CaosDB.Entity.get_unit(prop_with_name_and_unit) == "m" rec_with_parent_and_props = CaosDB.Entity.create_record("TestRec") # cannot set an ID @test_throws CaosDB.Exceptions.ClientException CaosDB.Entity.set_id( rec_with_parent_and_props, "some_id", ) # cannot set the datatype of a record @test_throws CaosDB.Exceptions.ClientException CaosDB.Entity.set_datatype( rec_with_parent_and_props, "INTEGER", ) par1 = CaosDB.Entity.create_parent(name = "Parent1") par2 = CaosDB.Entity.create_parent(name = "Parent2", id = "id_of_parent_2") CaosDB.Entity.append_parents(rec_with_parent_and_props, [par1, par2]) @test length(CaosDB.Entity.get_parents(rec_with_parent_and_props)) == 2 # Getting has to work with all Integers that can be cast to Cint @test CaosDB.Entity.get_name( CaosDB.Entity.get_parent(rec_with_parent_and_props, Cint(1)), ) == "Parent1" @test CaosDB.Entity.get_name( CaosDB.Entity.get_parent(rec_with_parent_and_props, 2), ) == "Parent2" @test_throws DomainError CaosDB.Entity.get_parent(rec_with_parent_and_props, 3) @test CaosDB.Entity.get_id( CaosDB.Entity.get_parent(rec_with_parent_and_props, Cint(2)), ) == "id_of_parent_2" CaosDB.Entity.remove_parent(rec_with_parent_and_props, Cint(1)) @test length(CaosDB.Entity.get_parents(rec_with_parent_and_props)) == 1 @test CaosDB.Entity.get_name( CaosDB.Entity.get_parent(rec_with_parent_and_props, Cint(1)), ) == "Parent2" prop1 = CaosDB.Entity.create_property(name = "Property1", value = "2") prop2 = CaosDB.Entity.create_property(id = "id_of_property_2") CaosDB.Entity.set_datatype(prop2, "TEXT") prop3 = CaosDB.Entity.create_property(name = "Property3") CaosDB.Entity.append_properties(rec_with_parent_and_props, [prop1, prop2, prop3]) @test length(CaosDB.Entity.get_properties(rec_with_parent_and_props)) == 3 # properties can be accessed as a list # TODO(florian) Fix this once we have a reasonable treatment of value objects in Extern C. @test_broken CaosDB.Entity.get_value( CaosDB.Entity.get_properties(rec_with_parent_and_props)[1], ) == "2" type, is_ref, is_list = CaosDB.Entity.get_datatype( CaosDB.Entity.get_properties(rec_with_parent_and_props)[2], ) @test type == "TEXT" @test is_ref == false @test is_list == false @test CaosDB.Entity.get_id( CaosDB.Entity.get_properties(rec_with_parent_and_props)[2], ) == "id_of_property_2" CaosDB.Entity.remove_property(rec_with_parent_and_props, Cint(2)) @test length(CaosDB.Entity.get_properties(rec_with_parent_and_props)) == 2 @test CaosDB.Entity.get_name( CaosDB.Entity.get_properties(rec_with_parent_and_props)[2], ) == "Property3" f = touch("caosdbfilefortests.txt") write(f, "Content") file_ent = CaosDB.Entity.create_file_entity( name = "TestFile", local_path = string(pwd(), "/", "caosdbfilefortests.txt"), remote_path = "/remote_path/file.txt", ) @test CaosDB.Entity.get_role(file_ent) == "FILE" @test CaosDB.Entity.get_name(file_ent) == "TestFile" # local file not found rm(string(pwd(), "/", "caosdbfilefortests.txt")) @test_throws CaosDB.Exceptions.ClientException CaosDB.Entity.create_file_entity( name = "TestFile", local_path = string(pwd(), "/", "caosdbfilefortests.txt"), remote_path = "/remote_path/file.txt", ) end @testset "Property values and datatypes" begin @testset "Entity properties" begin int_prop = CaosDB.Entity.create_property_entity(name = "IntProp", datatype = "INTEGER") double_prop = CaosDB.Entity.create_property_entity( name = "DoubleProp", datatype = "DOUBLE", ) bool_prop = CaosDB.Entity.create_property_entity( name = "BoolProp", datatype = "BOOLEAN", ) string_prop = CaosDB.Entity.create_property_entity(name = "StringProp", datatype = "TEXT") ref_prop = CaosDB.Entity.create_property_entity( name = "RefProp", datatype = "MyRefType", is_reference = true, ) CaosDB.Entity.set_value(int_prop, 123) CaosDB.Entity.set_value(double_prop, 10.246) CaosDB.Entity.set_value(bool_prop, true) CaosDB.Entity.set_value(string_prop, "Hello World") CaosDB.Entity.set_value(ref_prop, "some_id") @test CaosDB.Entity.get_value(int_prop) == 123 @test CaosDB.Entity.get_value(double_prop) == 10.246 @test CaosDB.Entity.get_value(bool_prop) === true @test CaosDB.Entity.get_value(string_prop) == "Hello World" @test CaosDB.Entity.get_value(ref_prop) == "some_id" @test isa(CaosDB.Entity.get_value(int_prop), Integer) @test isa(CaosDB.Entity.get_value(double_prop), Number) @test isa(CaosDB.Entity.get_value(bool_prop), Bool) @test isa(CaosDB.Entity.get_value(string_prop), String) @test isa(CaosDB.Entity.get_value(ref_prop), String) @test CaosDB.Entity.get_datatype(int_prop) == ("INTEGER", false, false) @test CaosDB.Entity.get_datatype(double_prop) == ("DOUBLE", false, false) @test CaosDB.Entity.get_datatype(bool_prop) == ("BOOLEAN", false, false) @test CaosDB.Entity.get_datatype(string_prop) == ("TEXT", false, false) @test CaosDB.Entity.get_datatype(ref_prop) == ("MyRefType", true, false) """ Test lists """ int_list_prop = CaosDB.Entity.create_property_entity( name = "IntProp", datatype = "INTEGER", is_list = true, ) double_list_prop = CaosDB.Entity.create_property_entity( name = "DoubleProp", datatype = "DOUBLE", is_list = true, ) bool_list_prop = CaosDB.Entity.create_property_entity( name = "BoolProp", datatype = "BOOLEAN", is_list = true, ) string_list_prop = CaosDB.Entity.create_property_entity( name = "StringProp", datatype = "TEXT", is_list = true, ) ref_list_prop = CaosDB.Entity.create_property_entity( name = "RefListProp", datatype = "MyRefType", is_list = true, is_reference = true, ) CaosDB.Entity.set_value(int_list_prop, [123, 456]) CaosDB.Entity.set_value(double_list_prop, [10.246, 3.14]) CaosDB.Entity.set_value(bool_list_prop, [true, false]) CaosDB.Entity.set_value(string_list_prop, ["Hello", "World"]) CaosDB.Entity.set_value(ref_list_prop, ["some_id", "another_id"]) @test CaosDB.Entity.get_value(int_list_prop) == [123, 456] @test CaosDB.Entity.get_value(double_list_prop) == [10.246, 3.14] @test CaosDB.Entity.get_value(bool_list_prop) == [true, false] @test CaosDB.Entity.get_value(string_list_prop) == ["Hello", "World"] @test CaosDB.Entity.get_value(ref_list_prop) == ["some_id", "another_id"] @test isa(CaosDB.Entity.get_value(int_list_prop), Vector{Clong}) @test isa(CaosDB.Entity.get_value(double_list_prop), Vector{Cdouble}) @test isa(CaosDB.Entity.get_value(bool_list_prop), Vector{Bool}) @test isa(CaosDB.Entity.get_value(string_list_prop), Vector{String}) @test isa(CaosDB.Entity.get_value(ref_list_prop), Vector{String}) @test CaosDB.Entity.get_datatype(int_list_prop) == ("INTEGER", false, true) @test CaosDB.Entity.get_datatype(double_list_prop) == ("DOUBLE", false, true) @test CaosDB.Entity.get_datatype(bool_list_prop) == ("BOOLEAN", false, true) @test CaosDB.Entity.get_datatype(string_list_prop) == ("TEXT", false, true) @test CaosDB.Entity.get_datatype(ref_list_prop) == ("MyRefType", true, true) end @testset "Property properties" begin int_prop = CaosDB.Entity.create_property(name = "IntProp", datatype = "INTEGER") double_prop = CaosDB.Entity.create_property(name = "DoubleProp", datatype = "DOUBLE") bool_prop = CaosDB.Entity.create_property(name = "BoolProp", datatype = "BOOLEAN") string_prop = CaosDB.Entity.create_property(name = "StringProp", datatype = "TEXT") ref_prop = CaosDB.Entity.create_property( name = "RefProp", datatype = "MyRefType", is_reference = true, ) CaosDB.Entity.set_value(int_prop, 123) CaosDB.Entity.set_value(double_prop, 10.246) CaosDB.Entity.set_value(bool_prop, true) CaosDB.Entity.set_value(string_prop, "Hello World") CaosDB.Entity.set_value(ref_prop, "some_id") @test CaosDB.Entity.get_value(int_prop) == 123 @test CaosDB.Entity.get_value(double_prop) == 10.246 @test CaosDB.Entity.get_value(bool_prop) === true @test CaosDB.Entity.get_value(string_prop) == "Hello World" @test CaosDB.Entity.get_value(ref_prop) == "some_id" @test isa(CaosDB.Entity.get_value(int_prop), Integer) @test isa(CaosDB.Entity.get_value(double_prop), Number) @test isa(CaosDB.Entity.get_value(bool_prop), Bool) @test isa(CaosDB.Entity.get_value(string_prop), String) @test isa(CaosDB.Entity.get_value(ref_prop), String) @test CaosDB.Entity.get_datatype(int_prop) == ("INTEGER", false, false) @test CaosDB.Entity.get_datatype(double_prop) == ("DOUBLE", false, false) @test CaosDB.Entity.get_datatype(bool_prop) == ("BOOLEAN", false, false) @test CaosDB.Entity.get_datatype(string_prop) == ("TEXT", false, false) @test CaosDB.Entity.get_datatype(ref_prop) == ("MyRefType", true, false) """ Test lists """ int_list_prop = CaosDB.Entity.create_property( name = "IntProp", datatype = "INTEGER", is_list = true, ) double_list_prop = CaosDB.Entity.create_property( name = "DoubleProp", datatype = "DOUBLE", is_list = true, ) bool_list_prop = CaosDB.Entity.create_property( name = "BoolProp", datatype = "BOOLEAN", is_list = true, ) string_list_prop = CaosDB.Entity.create_property( name = "StringProp", datatype = "TEXT", is_list = true, ) ref_list_prop = CaosDB.Entity.create_property( name = "RefListProp", datatype = "MyRefType", is_list = true, is_reference = true, ) CaosDB.Entity.set_value(int_list_prop, [123, 456]) CaosDB.Entity.set_value(double_list_prop, [10.246, 3.14]) CaosDB.Entity.set_value(bool_list_prop, [true, false]) CaosDB.Entity.set_value(string_list_prop, ["Hello", "World"]) CaosDB.Entity.set_value(ref_list_prop, ["some_id", "another_id"]) @test CaosDB.Entity.get_value(int_list_prop) == [123, 456] @test CaosDB.Entity.get_value(double_list_prop) == [10.246, 3.14] @test CaosDB.Entity.get_value(bool_list_prop) == [true, false] @test CaosDB.Entity.get_value(string_list_prop) == ["Hello", "World"] @test CaosDB.Entity.get_value(ref_list_prop) == ["some_id", "another_id"] @test isa(CaosDB.Entity.get_value(int_list_prop), Vector{Clong}) @test isa(CaosDB.Entity.get_value(double_list_prop), Vector{Cdouble}) @test isa(CaosDB.Entity.get_value(bool_list_prop), Vector{Bool}) @test isa(CaosDB.Entity.get_value(string_list_prop), Vector{String}) @test isa(CaosDB.Entity.get_value(ref_list_prop), Vector{String}) @test CaosDB.Entity.get_datatype(int_list_prop) == ("INTEGER", false, true) @test CaosDB.Entity.get_datatype(double_list_prop) == ("DOUBLE", false, true) @test CaosDB.Entity.get_datatype(bool_list_prop) == ("BOOLEAN", false, true) @test CaosDB.Entity.get_datatype(string_list_prop) == ("TEXT", false, true) @test CaosDB.Entity.get_datatype(ref_list_prop) == ("MyRefType", true, true) end end end