Select Git revision
test_issues_server.py
-
Daniel Hornung authored
Value in string queries may not start with large number of digits.
Daniel Hornung authoredValue in string queries may not start with large number of digits.
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
test_issues_server.py 56.04 KiB
# -*- coding: utf-8 -*-
# This file is a part of the CaosDB Project.
#
# Copyright (c) 2020 - 2022 IndiScale GmbH <info@indiscale.com>
# Copyright (c) 2022 Daniel Hornung <d.hornung@indiscale.com>
# Copyright (c) 2020 Florian Spreckelsen <f.spreckelsen@indiscale.com>
# Copyright (c) 2021 - 2022 Timm Fitschen <t.fitschen@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/>.
"""Tests for issues on gitlab.com, project caosdb-server."""
import math
import os
import tempfile
import time
import caosdb as db
import pytest
from caosdb import administration as admin
from caosdb.exceptions import (TransactionError, HTTPClientError)
CURATOR_ROLE = "curator"
def setup_module():
db.configure_connection()
try:
db.execute_query("FIND ENTITY WITH ID > 99").delete()
except Exception as delete_exc:
print(delete_exc)
try:
admin._delete_user("TestUser")
except Exception as delete_exc:
print(delete_exc)
try:
admin._delete_role(CURATOR_ROLE)
except Exception as delete_exc:
print(delete_exc)
def setup_function(function):
"""No setup required."""
setup_module()
def teardown_function(function):
"""Deleting entities again."""
setup_module()
# ########################### Issue tests start here #####################
def test_issue_39():
"""Query Language Bug - quotes around year
Test for https://gitlab.com/caosdb/caosdb-server/-/issues/39
"""
date_str = "2020-01-01"
prop_name = "Test_Date"
db.Property(name=prop_name, datatype=db.DATETIME).insert()
db.RecordType(name="Test_Type").add_property(name=prop_name).insert()
db.Record(name="Test_Record").add_parent(name="Test_Type").add_property(
name=prop_name, value=date_str).insert()
# Quotes around years should work in the query
ent = db.execute_query("FIND entity WITH A Test_Date IN \"2020\"",
unique=True)
assert ent.get_property(prop_name).value == date_str
# This should raise a transaction error
with pytest.raises(TransactionError):
db.execute_query("FIND entity WITH A Test_Date IN \"abcd\"")
@pytest.mark.xfail(reason="to be fixed in server repo")
def test_issue_62():
"""datatype is not changed when recordtype name changes
Tests for https://gitlab.com/caosdb/caosdb-server/-/issues/62
"""
db.RecordType(name="Test_RTA").insert()
db.Property(name="Test_Prop", datatype="Test_RTA").insert()
db.Record(name="Test_Record").add_parent(
name="Test_RTA").add_property(name="Test_Prop").insert()
# rename Test_RTA to Test_RTB
rtb = db.execute_query("FIND RecordType Test_RTA", unique=True)
rtb.name = "Test_RTB"
rtb.update()
# renaming has to be reflected in Test_Record and Test_Prop
rec = db.execute_query("FIND Record Test_Record", unique=True)
assert rec.parents[0].name == rtb.name
assert rec.get_property("Test_Prop").datatype == rtb.name
prop = db.execute_query("FIND Property Test_Prop", unique=True)
assert prop.datatype == rtb.name # fails; datatype not updated
# Can't use Test_RTA as datatype anymore
prop2 = db.Property(name="Test_Prop2", datatype="Test_RTA")
with pytest.raises(TransactionError) as exc:
prop2.insert()
assert "Unknown data type." in str(exc.value)
def test_issue_85_a():
"""SQLIntegrityConstraintViolationException for special inheritance patterns.
Tests for https://gitlab.com/caosdb/caosdb-server/-/issues/85
"""
A = db.RecordType(name="A")
B = db.RecordType(name="B")
C = db.RecordType(name="C")
B.add_parent(A)
# This order is important for the test to fail.
C.add_parent(B)
C.add_parent(C)
C.add_parent(A)
c = db.Container()
# c.extend([C, B, A]) # worked before #86 was fixed
# c.extend([C, A, B]) # worked before #86 was fixed
c.extend([B, C, A]) # insert() failed before #86 was fixed
c.insert() # Raised java.sql.SQLIntegrityConstraintViolationException:
# # Duplicate entry '12345-12346-12345' for key 'PRIMARY'
def test_issue_85_b():
"""SQLIntegrityConstraintViolationException for special inheritance patterns.
Tests for https://gitlab.com/caosdb/caosdb-server/-/issues/85
"""
A = db.RecordType(name="A")
B = db.RecordType(name="B")
C = db.RecordType(name="C")
A.insert()
B.insert()
C.insert()
B.add_parent(A)
B.update()
C.add_parent(B)
C.update()
C.add_parent(C)
C.update()
C.add_parent(A)
C.update() # Failed at this step
@pytest.mark.local_server
def test_issue_99():
"""Checksum updating failed with versioning enabled.
"""
# Using files in extroot, because this allows us to update the file
# content from the outside.
local_dir = os.path.join(db.get_config().get("IntegrationTests",
"test_files.test_insert_files_in_dir.local"),
"test_issue_99")
docker_dir = os.path.join(db.get_config().get("IntegrationTests",
"test_files.test_insert_files_in_dir.server"),
"test_issue_99")
os.makedirs(local_dir, exist_ok=True)
with tempfile.NamedTemporaryFile(dir=local_dir) as file_99:
# Create File entity in CaosDB
file_99.write("test 99\n".encode())
os.fchmod(file_99.fileno(), 0o744) # make the file world readable
cont = db.Container()
cont.insert(unique=False, raise_exception_on_error=False,
flags={"InsertFilesInDir": docker_dir})
dbfile = cont[0]
# Checksum should exist after a short time
time.sleep(0.1)
dbfile.retrieve()
assert dbfile.checksum is not None
def test_issue_110():
"""query ignores ID: FIND MusicalInstrument which is referenced by Analysis with ID=124 """
cont = db.Container()
A = db.RecordType(name="TypeA")
B = db.RecordType(name="TypeB")
prop = db.Property(name="prop_ba", datatype=db.REFERENCE)
# Referenced Records
a1 = db.Record().add_parent(A)
a2 = db.Record().add_parent(A)
# Referencing Records
b1 = db.Record().add_parent(B).add_property(prop, value=a1)
b2 = db.Record().add_parent(B).add_property(prop, value=a2)
cont.extend([A, B, prop, a1, a2, b1, b2])
cont.insert()
id_b1 = b1.id
query = "FIND TypeA WHICH IS REFERENCED BY TypeB WITH ID={}".format(id_b1)
print(query)
result = db.execute_query(query)
print(result)
assert len(result) == 1
print(result[0])
print(a1)
assert result[0].id == a1.id
def test_issue_120():
"""Editing entities that were created with a no longer existing user leads
to a server error.
The server should throw an error when CHECK_ENTITY_ACL_ROLES_MODE=MUST,
otherwise a warning.
"""
# insert an entity
entity = db.RecordType("TestRT").insert(flags={"ACL": None})
db.administration.set_server_property("CHECK_ENTITY_ACL_ROLES_MODE",
"SHOULD")
# update with non-existing user, realm and role
entity.deny(
realm="CaosDB",
username="NON_EXISTING_USER",
permission="USE:AS_REFERENCE")
entity.update(flags={"ACL": None})
assert entity.messages["Warning", 1104][0] == "User role does not exist."
entity.deny(
realm="NON_EXISTING_REALM",
username="NON_EXISTING_USER",
permission="USE:AS_REFERENCE")
entity.update(flags={"ACL": None})
assert entity.messages["Warning", 1104][0] == "User role does not exist."
entity.deny(
role="ALSO_NON_EXISTING_ROLE",
permission="USE:AS_REFERENCE")
entity.update(flags={"ACL": None})
assert entity.messages["Warning", 1104][0] == "User role does not exist."
def test_issue_134():
"""multiple white space characters after `FROM`"""
db.execute_query("SELECT pname FROM ename")
def test_issue_131():
"""white space before unit with strange character"""
rt = db.RecordType(name="TestType").insert()
prop = db.Property(name="TestProp", datatype=db.INTEGER, unit="€").insert()
rec = db.Record(name="TestRecord").add_property(
name=prop.name, value=101, unit="€")
rec.add_parent(rt)
rec.insert()
result_ids = [ent.id for ent in db.execute_query(
"FIND Entity WITH {} > 100 €".format(prop.name))]
assert rec.id in result_ids
result_ids = [ent.id for ent in db.execute_query(
"FIND Entity WITH {} > 100.5 €".format(prop.name))]
assert rec.id in result_ids
def test_issue_154_no_versioning():
""" FIND MusicalInstrument WITH Manufacturer = "Antonio Stradivari" and
FIND MusicalInstrument WITH Manufacturer != "Antonio Stradivari" """
rt_man = db.RecordType("Manufacturer")
rt_inst = db.RecordType("MusicalInstrument").add_property(rt_man)
rec_man = db.Record("Antonio Stradivari").add_parent("Manufacturer")
rec_man2 = db.Record("The other guy").add_parent("Manufacturer")
rec_inst = db.Record("Violin").add_parent(
"MusicalInstrument").add_property("Manufacturer", rec_man)
rec_inst2 = db.Record("Guitar").add_parent(
"MusicalInstrument").add_property("Manufacturer", rec_man2)
rec_inst3 = db.Record("Broken Record").add_parent("MusicalInstrument")
c = db.Container().extend([rt_man, rt_inst, rec_man, rec_inst, rec_man2,
rec_inst2, rec_inst3]).insert()
assert "Violin" not in [e.name for e in db.execute_query(
"FIND RECORD MusicalInstrument WITH Manufacturer != 'Antonio Stradivari'")]
assert "Violin" not in [e.name for e in db.execute_query(
"FIND RECORD MusicalInstrument WITH NOT Manufacturer = 'Antonio Stradivari'")]
assert len(db.execute_query("FIND ENTITY MusicalInstrument")) == 4
assert len(db.execute_query("FIND RECORD MusicalInstrument")) == 3
assert len(db.execute_query(
"FIND ENTITY MusicalInstrument WITH Manufacturer")) == 3
assert len(db.execute_query(
"FIND RECORD MusicalInstrument WITH Manufacturer")) == 2
assert rec_inst.id == db.execute_query(
"FIND ENTITY MusicalInstrument WITH Manufacturer = 'Antonio Stradivari'",
unique=True).id
assert len(db.execute_query(
"FIND ENTITY MusicalInstrument WITH NOT Manufacturer = 'Antonio Stradivari'")) == 3
assert len(db.execute_query(
"FIND RECORD MusicalInstrument WITH NOT Manufacturer = 'Antonio Stradivari'")) == 2
assert len(db.execute_query(
"FIND ENTITY MusicalInstrument WITH Manufacturer != 'Antonio Stradivari'")) == 1
assert len(db.execute_query(
"FIND RECORD MusicalInstrument WITH Manufacturer != 'Antonio Stradivari'")) == 1
def test_issue_154_with_versioning():
""" FIND MusicalInstrument WITH Manufacturer = "Antonio Stradivari" and
FIND MusicalInstrument WITH Manufacturer != "Antonio Stradivari" """
rt_man = db.RecordType("Manufacturer")
rt_inst = db.RecordType("MusicalInstrument").add_property(rt_man)
rec_man = db.Record("Antonio Stradivari").add_parent("Manufacturer")
rec_man2 = db.Record("The other guy").add_parent("Manufacturer")
rec_inst = db.Record("Violin").add_parent(
"MusicalInstrument").add_property("Manufacturer", rec_man)
rec_inst2 = db.Record("Guitar").add_parent(
"MusicalInstrument").add_property("Manufacturer", rec_man2)
rec_inst3 = db.Record("Broken Record").add_parent("MusicalInstrument")
db.Container().extend([rt_man, rt_inst, rec_man,
rec_inst, rec_man2, rec_inst2, rec_inst3]).insert()
assert "Violin" not in [e.name for e in db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH Manufacturer != 'Antonio Stradivari'")]
assert "Violin" not in [e.name for e in db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH NOT Manufacturer = 'Antonio Stradivari'")]
assert len(db.execute_query("FIND ANY VERSION OF ENTITY MusicalInstrument")) == 4
assert len(db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument")) == 3
assert len(db.execute_query(
"FIND ANY VERSION OF ENTITY MusicalInstrument WITH Manufacturer")) == 3
assert len(db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH Manufacturer")) == 2
assert rec_inst.id == db.execute_query(
"FIND ANY VERSION OF ENTITY MusicalInstrument WITH Manufacturer = 'Antonio Stradivari'",
unique=True).id
assert len(db.execute_query(
"FIND ANY VERSION OF ENTITY MusicalInstrument WITH NOT Manufacturer = 'Antonio Stradivari'")) == 3
assert len(db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH NOT Manufacturer = 'Antonio Stradivari'")) == 2
assert len(db.execute_query(
"FIND ANY VERSION OF ENTITY MusicalInstrument WITH Manufacturer != 'Antonio Stradivari'")) == 1
assert len(db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH Manufacturer != 'Antonio Stradivari'")) == 1
# now, some updates
rt_man.description = "Updated Description"
rt_inst.description = "Updated Description"
rec_man.description = "Updated Description"
rec_man2.description = "Updated Description"
rec_inst.description = "Updated Description"
rec_inst2.description = "Updated Description"
rec_inst3.description = "Updated Description"
db.Container().extend([rt_man, rt_inst, rec_man,
rec_inst, rec_man2, rec_inst2, rec_inst3]).update()
assert "Violin" not in [e.name for e in db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH Manufacturer != 'Antonio Stradivari'")]
assert "Violin" not in [e.name for e in db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH NOT Manufacturer = 'Antonio Stradivari'")]
assert len(db.execute_query("FIND ANY VERSION OF ENTITY MusicalInstrument")) == 8
assert len(db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument")) == 6
assert len(db.execute_query(
"FIND ANY VERSION OF ENTITY MusicalInstrument WITH Manufacturer")) == 6
assert len(db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH Manufacturer")) == 4
assert len(db.execute_query(
"FIND ANY VERSION OF ENTITY MusicalInstrument WITH Manufacturer = 'Antonio Stradivari'")) == 2
assert len(db.execute_query(
"FIND ANY VERSION OF ENTITY MusicalInstrument WITH NOT Manufacturer = 'Antonio Stradivari'")) == 6
assert len(db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH NOT Manufacturer = 'Antonio Stradivari'")) == 4
assert len(db.execute_query(
"FIND ANY VERSION OF ENTITY MusicalInstrument WITH Manufacturer != 'Antonio Stradivari'")) == 2
assert len(db.execute_query(
"FIND ANY VERSION OF RECORD MusicalInstrument WITH Manufacturer != 'Antonio Stradivari'")) == 2
def test_issue_127():
"""https://gitlab.com/caosdb/caosdb-server/-/issues/127"""
p = db.Property(
name="TestDoubleProperty",
datatype=db.LIST(
db.DOUBLE)).insert()
rt = db.RecordType(name="TestRecordType").add_property(name="TestDoubleProperty",
value=["nan"]).insert()
test1 = db.execute_query("FIND ENTITY TestRecordType", unique=True)
assert math.isnan(test1.get_property("TestDoubleProperty").value[0])
test2 = db.execute_query(
"FIND ENTITY TestRecordType WITH TestDoubleProperty = NaN", unique=True)
assert math.isnan(test1.get_property("TestDoubleProperty").value[0])
def test_issue_170():
"""update scalar data type to list data type"""
p = db.Property(name="TestProp1", datatype=db.LIST(db.INTEGER))
p.value = [1, 2]
p.insert()
p2 = db.execute_query("FIND ENTITY TestProp1", unique=True)
assert p2.datatype == db.LIST(db.INTEGER)
assert p2.value == [1, 2]
p.description = "TestDescription"
p.update() # this failed
p2 = db.execute_query("FIND ENTITY TestProp1", unique=True)
assert p2.datatype == db.LIST(db.INTEGER)
assert p2.value == [1, 2]
assert p2.description == "TestDescription"
p = db.Property(name="TestProp2", datatype=db.DOUBLE)
p.insert()
p.datatype = db.LIST(db.INTEGER)
p.update() # this worked because no value yet
p2 = db.execute_query("FIND ENTITY TestProp2", unique=True)
assert p2.datatype == db.LIST(db.INTEGER)
p.value = [1, 2]
p.update() # this failed
p2 = db.execute_query("FIND ENTITY TestProp2", unique=True)
assert p2.datatype == db.LIST(db.INTEGER)
assert p2.value == [1, 2]
p = db.Property(name="TestProp3", datatype=db.DOUBLE)
p.insert()
p.datatype = db.LIST(db.INTEGER)
p.value = [1, 2]
p.update() # this failed
p2 = db.execute_query("FIND ENTITY TestProp3", unique=True)
assert p2.datatype == db.LIST(db.INTEGER)
assert p2.value == [1, 2]
def test_issue_181():
"""https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/181"""
rt = db.RecordType("TestRT").insert()
assert len(db.execute_query("FIND RECORDTYPE TestRT")) == 1
assert len(db.execute_query(
"FIND RECORDTYPE TestRT WHICH HAS BEEN UPDATED TODAY")) == 0
rt.description = "New description"
rt.update()
assert len(db.execute_query(
"FIND RECORDTYPE TestRT WHICH HAS BEEN UPDATED TODAY")) == 1
def test_issue_183():
"""No reasonable error when using bad datetime format.
https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/183
"""
# Date YYYY-MM-ddThh:mm:ss
assert db.Property(name="TestDateTime", datatype=db.DATETIME,
value="2015-05-05T20:15:00").insert().id is not None
with pytest.raises(db.TransactionError) as cm:
# Date YYYY-MM-ddThh:mm
db.Property(name="TestDateTime2", datatype=db.DATETIME,
value="2015-05-05T20:15").insert()
assert cm.value.errors[0].msg == ("Cannot parse value to datetime format "
"(yyyy-mm-dd'T'hh:mm:ss[.fffffffff][TimeZone]).")
def test_issue_130():
"""Test select queries where names contain spaces
https://gitlab.com/caosdb/caosdb-server/-/issues/130
However, this bug was actually about quotation marks
"""
db.RecordType(name="TestRT_A").insert()
r1 = db.Record("ReferencedRecord").add_parent("TestRT_A").insert()
p1 = db.Property(name="TestWrapper", datatype="TestRT_A").insert()
p2 = db.Property(
name="TestWrapper With Spaces",
datatype="TestRT_A").insert()
db.RecordType(name="TestRT_B"
).add_property(name="TestWrapper"
).add_property("TestWrapper With Spaces"
).insert()
db.Record().add_parent("TestRT_B"
).add_property("TestWrapper", value=r1
).add_property("TestWrapper With Spaces",
value=r1
).insert()
query = "SELECT TestWrapper FROM RECORD TestRT_B"
row = db.execute_query(query).get_property_values(("TestWrapper"))
assert row == [(r1.id,)]
query = "SELECT TestWrapper FROM RECORD TestRT_B"
row = db.execute_query(query).get_property_values(("TestWrapper", "id"))
assert row == [(p1.id,)]
query = "SELECT 'TestWrapper' FROM RECORD TestRT_B"
row = db.execute_query(query).get_property_values(("TestWrapper", "id"))
assert row == [(p1.id,)]
query = "SELECT TestWrapper FROM RECORD TestRT_B"
row = db.execute_query(query).get_property_values(("TestWrapper", "name"))
assert row == [("TestWrapper",)]
query = "SELECT TestWrapper.name FROM RECORD TestRT_B"
row = db.execute_query(query).get_property_values(("TestWrapper", "name"))
assert row == [("ReferencedRecord",)]
query = "SELECT 'TestWrapper.name' FROM RECORD TestRT_B"
rec = db.execute_query(query, unique=True)
assert len(rec.properties) == 0
query = "SELECT 'TestWrapper'.name FROM RECORD TestRT_B"
row = db.execute_query(query).get_property_values(("TestWrapper", "name"))
assert row == [("ReferencedRecord",)]
query = "SELECT TestWrapper With Spaces FROM RECORD TestRT_B"
row = db.execute_query(query).get_property_values(
("TestWrapper With Spaces"))
assert row == [(r1.id,)]
query = "SELECT TestWrapper With Spaces FROM RECORD TestRT_B"
row = db.execute_query(query).get_property_values(
("TestWrapper With Spaces", "id"))
assert row == [(p2.id,)]
query = 'SELECT TestWrapper With Spaces FROM RECORD TestRT_B'
row = db.execute_query(query).get_property_values(
("TestWrapper With Spaces", "name"))
assert row == [("TestWrapper With Spaces",)]
query = 'SELECT "TestWrapper With Spaces" FROM RECORD TestRT_B'
row = db.execute_query(query).get_property_values(
("TestWrapper With Spaces", "name"))
assert row == [("TestWrapper With Spaces",)]
query = 'SELECT TestWrapper With Spaces.name FROM RECORD TestRT_B'
row = db.execute_query(query).get_property_values(
("TestWrapper With Spaces", "name"))
assert row == [("ReferencedRecord",)]
query = 'SELECT "TestWrapper With Spaces".name FROM RECORD TestRT_B'
row = db.execute_query(query).get_property_values(
("TestWrapper With Spaces", "name"))
assert row == [("ReferencedRecord",)]
def test_issue_132():
"""Query: Parenthesis around subproperties.
https://gitlab.com/caosdb/caosdb-server/-/issues/132
"""
db.RecordType("TestRT").insert()
db.RecordType("TestRT_Foo").insert()
db.Property("TestP_Bar", datatype=db.TEXT).insert()
db.Property("TestP_Baz", datatype=db.TEXT).insert()
rt1 = db.Record().add_parent("TestRT_Foo").add_property(
"TestP_Bar", "val1").add_property(
"TestP_Baz", "the other baz").insert()
rt2 = db.Record().add_parent("TestRT").add_property(
"TestP_Baz", "val2").add_property(
"TestRT_Foo", rt1).insert()
query = "FIND RECORD TestRT_Foo"
assert db.execute_query(query, unique=True).id == rt1.id
query = "FIND RECORD TestRT"
assert db.execute_query(query, unique=True).id == rt2.id
query = "FIND RECORD TestRT WITH TestRT_Foo"
assert db.execute_query(query, unique=True).id == rt2.id
query = "FIND RECORD TestRT WITH TestRT_Foo.TestP_Bar"
assert db.execute_query(query, unique=True).id == rt2.id
query = "FIND RECORD TestRT WITH TestRT_Foo.TestP_Bar = val1"
assert db.execute_query(query, unique=True).id == rt2.id
query = "FIND RECORD TestRT WITH (TestRT_Foo.TestP_Bar = val1)"
assert db.execute_query(query, unique=True).id == rt2.id
query = "FIND RECORD TestRT WITH ( TestRT_Foo.TestP_Bar = val1 )"
assert db.execute_query(query, unique=True).id == rt2.id
query = "FIND RECORD TestRT WITH (TestRT_Foo.TestP_Bar = val1) AND TestP_Baz = val2"
assert db.execute_query(query, unique=True).id == rt2.id
query = "FIND RECORD TestRT WITH (TestRT_Foo WITH (TestP_Bar = val1 AND TestP_Baz = 'the other baz')) AND TestP_Baz = val2"
assert db.execute_query(query, unique=True).id == rt2.id
query = "FIND RECORD TestRT WITH TestRT_Foo WITH (TestP_Bar = val1 AND TestP_Baz = 'the other baz') AND TestP_Baz = val2"
assert db.execute_query(query, unique=True).id == rt2.id
# this one has the wront scope of the conjunction.
query = "FIND RECORD TestRT WITH TestRT_Foo.TestP_Bar = val1 AND TestP_Baz = 'the other one'"
assert len(db.execute_query(query)) == 0
def test_issue_217():
"""Server gets list property datatype wrong if description is updated."""
# @review Florian Spreckelsen 2022-03-15
rt = db.RecordType(name="TestRT").insert()
# prop = db.Property(name="LP", datatype=db.LIST("TestRT")).insert()
r = db.Record().add_parent(id=rt.id).add_property(name=rt.name,
datatype=db.LIST(
db.INTEGER),
value=[10001, 10002])
assert r.get_property(rt.name).datatype == db.LIST(db.INTEGER)
assert r.get_property(rt.name).value == [10001, 10002]
r.insert()
assert r.get_property(rt.name).datatype == db.LIST(db.INTEGER)
assert r.get_property(rt.name).value == [10001, 10002]
r.retrieve()
assert r.get_property(rt.name).datatype == db.LIST(db.INTEGER)
assert r.get_property(rt.name).value == [10001, 10002]
r.retrieve(flags={"cache": "false"})
assert r.get_property(rt.name).datatype == db.LIST(db.INTEGER)
assert r.get_property(rt.name).value == [10001, 10002]
r.description = "Changed description"
r.update()
assert r.get_property(rt.name).datatype == db.LIST(db.INTEGER)
assert r.get_property(rt.name).value == [10001, 10002]
# This line fails in the bug report with invalid XML.
r.retrieve()
assert r.get_property(rt.name).datatype == db.LIST(db.INTEGER)
assert r.get_property(rt.name).value == [10001, 10002]
def test_issue_217_2():
"""Server gets overridden name of property wrong when the description of record is being updated."""
# @review Florian Spreckelsen 2022-03-15
rt = db.RecordType(name="TestRT").insert()
# prop = db.Property(name="LP", datatype=db.LIST("TestRT")).insert()
overridden_name = "TestRT-overridden"
r = db.Record().add_parent(id=rt.id).add_property(name=overridden_name,
id=rt.id)
assert r.get_property(overridden_name) is not None
assert r.get_property(overridden_name).id == rt.id
r.insert()
assert r.get_property(overridden_name) is not None
assert r.get_property(overridden_name).id == rt.id
r.retrieve()
assert r.get_property(overridden_name) is not None
assert r.get_property(overridden_name).id == rt.id
r.retrieve(flags={"cache": "false"})
assert r.get_property(overridden_name) is not None
assert r.get_property(overridden_name).id == rt.id
r.description = "Changed description" # change description of the record
r.update()
assert r.get_property(overridden_name) is not None
assert r.get_property(overridden_name).id == rt.id
r.retrieve()
assert r.get_property(overridden_name) is not None
assert r.get_property(overridden_name).id == rt.id
def test_issue_217_3():
"""Server gets overridden description of property wrong when the description of record is being updated."""
# @review Florian Spreckelsen 2022-03-15
rt = db.RecordType(name="TestRT", description="Desc").insert()
# prop = db.Property(name="LP", datatype=db.LIST("TestRT")).insert()
r = db.Record().add_parent(id=rt.id).add_property(description="Desc-overridden",
id=rt.id)
r.insert()
assert r.get_property(rt.name).id == rt.id
assert r.get_property(rt.name).description == "Desc-overridden"
r.retrieve()
assert r.get_property(rt.name).id == rt.id
assert r.get_property(rt.name).description == "Desc-overridden"
r.retrieve(flags={"cache": "false"})
assert r.get_property(rt.name).id == rt.id
assert r.get_property(rt.name).description == "Desc-overridden"
r.description = "Changed description" # change description of the record
r.update()
assert r.get_property(rt.name).id == rt.id
assert r.get_property(rt.name).description == "Desc-overridden"
r.retrieve()
assert r.get_property(rt.name).id == rt.id
assert r.get_property(rt.name).description == "Desc-overridden"
def test_issue_221():
"""Unknown error during update of property leaving out datatype"""
rt = db.RecordType("A")
r = db.Record()
r.add_parent(rt)
p = db.Property(name="B", datatype=db.INTEGER)
r.add_property(name="B", value=5)
db.Container().extend([rt, r, p]).insert()
r2 = db.Record(id=r.id).retrieve()
r2.remove_property("B")
r2.add_property(p, value=7)
r2.update()
assert r2.get_property("B").value == 7
assert r2.get_property("B").datatype == db.INTEGER
assert r2.get_property("B").id == p.id
def test_134_1():
"""CQL: Subproperties are not recognized in list of references.
https://gitlab.com/caosdb/caosdb-server/-/issues/134
"""
p_lng = db.Property(name="longitude", datatype=db.DOUBLE).insert()
p_lat = db.Property(name="latitude", datatype=db.DOUBLE).insert()
rt_ev = db.RecordType(name="Event").add_property(
p_lng).add_property(p_lat).insert()
p_ev = db.Property(name="events", datatype=db.LIST(rt_ev)).insert()
rt_ds = db.RecordType(name="DataSet").add_property(p_ev).insert()
r_ev_1 = db.Record().add_parent("Event").add_property("longitude",
0.1).add_property("latitude",
0.1).insert()
r_ev_2 = db.Record().add_parent("Event").add_property("longitude",
0.2).add_property("latitude",
0.2).insert()
r_ds = db.Record().add_parent("DataSet").add_property(
"events", value=[r_ev_1, r_ev_2]).insert()
result = db.execute_query("SELECT events.latitude FROM RECORD DataSet",
unique=True)
print(result)
assert len(result.get_property("events").value) == 2
assert result.get_property("events").value[0].get_property(
"latitude").value == 0.1
assert result.get_property("events").value[1].get_property(
"latitude").value == 0.2
def test_134_2():
"""CQL: Subproperties are not recognized in list of references.
https://gitlab.com/caosdb/caosdb-server/-/issues/134
"""
p_lng = db.Property(name="longitude", datatype=db.DOUBLE).insert()
p_lat = db.Property(name="latitude", datatype=db.DOUBLE).insert()
rt_ev = db.RecordType(name="Event").add_property(
p_lng).add_property(p_lat).insert()
rt_ds = db.RecordType(name="DataSet").add_property(name="Event",
datatype=db.LIST(rt_ev)).insert()
r_ev_1 = db.Record().add_parent("Event").add_property("longitude",
0.1).add_property("latitude",
0.1).insert()
r_ev_2 = db.Record().add_parent("Event").add_property("longitude",
0.2).add_property("latitude",
0.2).insert()
r_ds = db.Record().add_parent("DataSet").add_property(
"Event", datatype=db.LIST(rt_ev), value=[r_ev_1, r_ev_2]).insert()
result = db.execute_query("SELECT Event.latitude FROM RECORD DataSet",
unique=True)
assert len(result.get_property("Event").value) == 2
assert result.get_property("Event").value[0].get_property(
"latitude").value == 0.1
assert result.get_property("Event").value[1].get_property(
"latitude").value == 0.2
def test_136():
"""Faulty creation of a multi-property when updating a non-list property
with a list value.
https://gitlab.com/caosdb/caosdb-server/-/issues/136
"""
# @author Florian Spreckelsen
# @date 2022-05-23
# Insert data model:
rt = db.RecordType(name="TestBug")
p = db.Property(name="TestBugProperty", datatype=db.INTEGER)
db.Container().extend([rt, p]).insert()
# Insert test record:
r = db.Record(name="TestRecord")
r.add_parent(rt)
r.add_property(p, value=18)
r.insert()
# Update the record:
test_r = db.Record(id=r.id).retrieve()
test_r.add_parent(rt)
test_r.add_property(id=p.id, value=[18, 12])
with pytest.raises(db.TransactionError) as err:
test_r.update()
te = err.value
assert te.has_error(db.UnqualifiedPropertiesError)
assert "This data type does not accept collections of values (e.g. Lists)" in str(te)
@pytest.mark.xfail(reason="Fix https://gitlab.com/caosdb/caosdb-pylib/-/issues/81")
def test_136_b():
"""Faulty creation of a multi-property when updating a non-list property
with a list value.
https://gitlab.com/caosdb/caosdb-server/-/issues/136
"""
# @author Florian Spreckelsen
# @date 2022-05-23
# Insert data model:
rt = db.RecordType(name="TestBug")
p = db.Property(name="TestBugProperty", datatype=db.TEXT)
db.Container().extend([rt, p]).insert()
# Insert test record:
r = db.Record(name="TestRecord")
r.add_parent(rt)
r.add_property(p, value="val1")
r.insert()
# Update the record:
test_r = db.Record(id=r.id).retrieve()
test_r.add_parent(rt)
test_r.add_property(id=p.id, value=["val1", "val2"])
with pytest.raises(db.TransactionError) as err:
test_r.update()
te = err.value
assert te.has_error(db.UnqualifiedPropertiesError)
assert "This data type does not accept collections of values (e.g. Lists)" in str(te)
def test_141():
"""Roles with `Grant(*)P` permissions still can't update other people's
entities."""
admin._insert_role(name=CURATOR_ROLE, description="Desc")
perms = admin._get_permissions(CURATOR_ROLE)
g = admin.PermissionRule(action="Grant", permission="*", priority=True)
d = admin.PermissionRule(action="Deny", permission="*", priority=True)
if g in perms:
perms.remove(g)
if d in perms:
perms.remove(d)
perms.add(g)
admin._set_permissions(CURATOR_ROLE, permission_rules=perms)
perms = admin._get_permissions(CURATOR_ROLE)
print(perms)
rt = db.RecordType(name="TestRT", description="Desc1").insert()
admin._insert_user(name="TestUser", password="Password1!", status="ACTIVE")
admin._set_roles(username="TestUser", roles=[CURATOR_ROLE])
db.configure_connection(username="TestUser", password_method="plain",
password="Password1!")
assert db.Info().user_info.name == "TestUser"
assert db.Info().user_info.roles == [CURATOR_ROLE]
rt.description = "Desc2"
rt.update()
assert rt.description == "Desc2"
# switch back to admin user
db.configure_connection()
assert db.execute_query("FIND ENTITY TestRT", unique=True).description == "Desc2"
def test_145():
"""Searching for large numbers results in wrong results if integer values
are used.
https://gitlab.com/caosdb/caosdb-server/-/issues/145
"""
db.Property("TestProp", datatype=db.TEXT).insert()
db.Property("TestPropInt", datatype=db.INTEGER).add_parent(
"TestProp").insert()
db.Property("TestPropDouble", datatype=db.DOUBLE).add_parent(
"TestProp").insert()
db.RecordType("TestRT").insert()
rec1 = db.Record("TestRec1").add_parent("TestRT").add_property(
"TestPropInt", 1_000_000_000).insert()
assert rec1.get_property("TestPropInt").value == 1_000_000_000
assert isinstance(rec1.get_property("TestPropInt").value, int)
rec2 = db.Record("TestRec2").add_parent("TestRT").add_property(
"TestPropDouble", 20_000_000_000).insert()
assert rec2.get_property("TestPropDouble").value == 20_000_000_000
assert isinstance(rec2.get_property("TestPropDouble").value, float)
assert db.execute_query(
"FIND TestRT WITH TestProp = 1000000000", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT WITH TestProp = 1000000000.0", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT WITH TestProp > 1000000000", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT WITH TestProp > 1000000000.0", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT WITH TestProp = 20000000000", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT WITH TestProp = 20000000000.0", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT WITH TestProp < 20000000000", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT WITH TestProp < 20000000000.0", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT WITH TestPropInt < 10000000000000000000000000000000000000000000000000000000000",
unique=True).id == rec1.id
@pytest.mark.xfail(reason="Fix https://gitlab.com/caosdb/caosdb-server/-/issues/147")
def test_147():
"""Searching for integer numbers results in wrong results if floats are used.
https://gitlab.com/caosdb/caosdb-server/-/issues/147
"""
db.Property("TestProp", datatype=db.TEXT).insert()
db.Property("TestPropInt", datatype=db.INTEGER).add_parent(
"TestProp").insert()
db.RecordType("TestRT1").insert()
db.RecordType("TestRT2").insert()
rec1 = db.Record("TestRec1").add_parent("TestRT1").add_property(
"TestPropInt", 1).insert()
assert rec1.get_property("TestPropInt").value == 1
assert isinstance(rec1.get_property("TestPropInt").value, int)
rec2 = db.Record("TestRec2").add_parent("TestRT2").add_property(
"TestPropInt", -2).insert()
# Find the records
assert db.execute_query(
"FIND TestRT1 WITH TestProp < 1.9", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT1 WITH TestProp < 1.1", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT1 WITH TestProp = 1.0", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT1 WITH TestProp > 0.9", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT1 WITH TestProp > 0.1", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT1 WITH TestProp <= 1.9", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT1 WITH TestProp <= 1.1", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT1 WITH TestProp >= 0.9", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT1 WITH TestProp >= 0.1", unique=True).id == rec1.id
assert db.execute_query(
"FIND TestRT2 WITH TestProp < -1.1", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT2 WITH TestProp < -1.9", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT2 WITH TestProp = -2.0", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT2 WITH TestProp > -2.1", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT2 WITH TestProp > 2.9", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT2 WITH TestProp <= -1.1", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT2 WITH TestProp <= -1.9", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT2 WITH TestProp >= -2.1", unique=True).id == rec2.id
assert db.execute_query(
"FIND TestRT2 WITH TestProp >= 2.9", unique=True).id == rec2.id
# Don't find the records
assert len(db.execute_query("FIND TestRT1 WITH TestProp < 0.9")) == 0
assert len(db.execute_query("FIND TestRT1 WITH TestProp <= 0.9")) == 0
assert len(db.execute_query("FIND TestRT1 WITH TestProp > 1.1")) == 0
assert len(db.execute_query("FIND TestRT1 WITH TestProp >= 1.1")) == 0
assert len(db.execute_query("FIND TestRT2 WITH TestProp > -1.9")) == 0
assert len(db.execute_query("FIND TestRT2 WITH TestProp >= -1.9")) == 0
assert len(db.execute_query("FIND TestRT2 WITH TestProp < -2.1")) == 0
assert len(db.execute_query("FIND TestRT2 WITH TestProp <= -2.1")) == 0
# Smaller numbers, but querying across number types.
rec3 = db.Record("TestRec3").add_parent(
"TestRT").add_property("TestPropInt", 1).insert()
assert db.execute_query(
"FIND TestRT WITH TestPropInt < 2", unique=True).id == rec3.id
assert db.execute_query(
"FIND TestRT WITH TestPropInt < 2.5", unique=True).id == rec3.id
def test_140():
"""https://gitlab.com/caosdb/caosdb-server/-/issues/140"""
admin._insert_role(name=CURATOR_ROLE, description="Desc")
perms = admin._get_permissions(CURATOR_ROLE)
g = admin.PermissionRule(action="Grant", permission="TRANSACTION:*")
perms.add(g)
admin._set_permissions(CURATOR_ROLE, permission_rules=perms)
admin._insert_user(name="TestUser", password="Password1!", status="ACTIVE")
admin._set_roles(username="TestUser", roles=[CURATOR_ROLE])
core_model_deny_permissions = [
"DELETE",
"UPDATE:*",
"EDIT:ACL"
]
core_model_grant_permissions = [
"RETRIEVE:*",
"USE:*",
"UPDATE:PROPERTY:ADD"
]
prop = db.Property(name="TestProp", datatype=db.TEXT).insert()
rt = db.RecordType(name="TestRT").insert(flags={"ACL": None})
for d in core_model_deny_permissions:
# First deny s.th. later the "UPDATE:PROPERTY:ADD" permission can be granted explicitely
rt.deny(role=CURATOR_ROLE, permission=d)
rt.update_acl()
# retrieve again to be sure
rt.retrieve(flags={"ACL": None})
for g in core_model_grant_permissions:
rt.grant(role=CURATOR_ROLE, permission=g)
rt.update_acl()
print(rt.acl)
db.configure_connection(username="TestUser", password_method="plain",
password="Password1!")
assert db.Info().user_info.name == "TestUser"
assert db.Info().user_info.roles == [CURATOR_ROLE]
rt.add_property(prop)
rt.get_property("TestProp").value = "some value"
# this should succeed because the curator has UPDATE:PROPERTY:ADD
rt.update()
assert rt.get_property("TestProp").value == "some value"
rt.get_property("TestProp").value = "some other value"
with pytest.raises(TransactionError) as cm:
# this should fail because the curator doesn't have
# UPDATE:PROPERTY:REMOVE
rt.update()
assert cm.value.errors[0].msg == "You are not allowed to do this."
def test_142():
"""https://gitlab.com/caosdb/caosdb-server/-/issues/142"""
valid_names = [
"with.dot",
"with-hyphen",
"with_underbar",
"with0number",
"withAcapital",
".withleadingdot",
"Bwithleadingcapital",
"1withleadingnumber",
"_withleadingunderbar",
"withtrailingcapitalC",
"withtrailingnumber2",
"withtrailingunderbar_",
"withtrailinghyphen-",
"withtrailingdot.",
"4",
"_",
"D",
"d",
".",
]
invalid_names = [
"-",
"-leadinghyphen",
"",
"%",
"/",
"[asdf]",
"?",
'"',
]
for name in valid_names:
admin._insert_user(
name=name,
password="Password1!",
status="ACTIVE",
email=None,
entity=None)
admin._delete_user(name=name)
for name in invalid_names:
with pytest.raises(HTTPClientError) as cm:
admin._insert_user(
name=name,
password="Password1!",
status="ACTIVE",
email=None,
entity=None)
admin._delete_user(name=name)
assert cm.value.status == 400
assert cm.value.msg.startswith(
"The user name does not comply with the current policies for user names")
@pytest.mark.xfail(reason="Fix https://gitlab.com/caosdb/caosdb-server/-/issues/177")
def test_177():
db.RecordType("TestRT").insert()
db.RecordType("TestRT").insert(unique=False)
db.Property("TestProp", datatype=db.TEXT).insert()
db.RecordType("TestSubRT").add_property("TestProp").add_parent("TestRT").insert()
@pytest.mark.xfail(reason="Fix https://gitlab.com/caosdb/caosdb-server/-/issues/135")
def test_135():
db.RecordType("TestRT1").insert()
db.Property("TestProp", datatype=db.LIST("TestRT1")).insert()
r1 = db.Record().add_parent("TestRT1").insert()
r2 = db.Record().add_parent("TestRT1").add_property("TestProp", r1).insert()
assert len(db.execute_query("FIND ENTITY WHICH IS REFERENCED BY A TestRT1 AS TestProp")) == 1
def test_192():
"""Testing queries with Property by name.
See https://gitlab.com/caosdb/caosdb-server/-/issues/192
COUNT Record WHICH HAS price -> Results: 19
COUNT Record WHICH HAS Property price -> Results: 19
COUNT Record WITH price -> Results: 19
COUNT Record WITH Property price -> Results: 0
"""
db.Property(name="testprop", datatype=db.DOUBLE).insert()
db.RecordType(name="TestRT").add_property("testprop").insert()
db.Record(name="Rec1").add_parent("TestRT").add_property("testprop", value=3.1).insert()
query1 = "COUNT RECORD WHICH HAS testprop"
query2 = "COUNT RECORD WHICH HAS A testprop"
query3 = "COUNT RECORD WHICH HAS Property testprop"
query4 = "COUNT RECORD WHICH HAS A Property testprop"
query5 = "COUNT RECORD WITH testprop"
query6 = "COUNT RECORD WITH A testprop"
query7 = "COUNT RECORD WITH Property testprop"
query8 = "COUNT RECORD WITH A Property testprop"
count1 = db.execute_query(query1)
count2 = db.execute_query(query2)
count3 = db.execute_query(query3)
count4 = db.execute_query(query4)
count5 = db.execute_query(query5)
count6 = db.execute_query(query6)
count7 = db.execute_query(query7)
count8 = db.execute_query(query8)
assert count1 == 1
assert count2 == 1
assert count3 == 1
assert count4 == 1
assert count5 == 1
assert count6 == 1
assert count7 == 1
assert count8 == 1
def test_196a():
"""See https://gitlab.com/caosdb/caosdb-server/-/issues/196"""
admin._insert_role(name=CURATOR_ROLE, description="Desc")
perms = admin._get_permissions(CURATOR_ROLE)
g = admin.PermissionRule(action="Grant", permission="TRANSACTION:*")
perms.add(g)
admin._set_permissions(CURATOR_ROLE, permission_rules=perms)
admin._insert_user(name="TestUser", password="Password1!", status="ACTIVE")
admin._set_roles(username="TestUser", roles=[CURATOR_ROLE])
db.configure_connection(username="TestUser", password_method="plain",
password="Password1!")
# works
db.RecordType(name="TestRT1").insert()
db.Property(name="TestProp1", datatype=db.TEXT).insert()
# Deny TRANSACTION:INSERT:PROPERTY
db.configure_connection()
perms = admin._get_permissions(CURATOR_ROLE)
g = admin.PermissionRule(action="Deny", permission="TRANSACTION:INSERT:PROPERTY")
perms.add(g)
admin._set_permissions(CURATOR_ROLE, permission_rules=perms)
db.configure_connection(username="TestUser", password_method="plain",
password="Password1!")
# it is still allowed to insert a record type...
db.RecordType(name="TestRT2").insert()
# fails
with pytest.raises(TransactionError) as cm:
# this should fail because the curator doesn't have TRANSACTION:INSERT:PROPERTY
db.Property(name="TestProp2", datatype=db.TEXT).insert()
assert cm.value.errors[0].msg == "You are not allowed to do this."
@pytest.mark.parametrize("deny", ["TRANSACTION:INSERT:", "TRANSACTION:INSERT:*"])
def test_196b(deny):
"""Same as test_196a but we completely deny insertion."""
admin._insert_role(name=CURATOR_ROLE, description="Desc")
perms = admin._get_permissions(CURATOR_ROLE)
g = admin.PermissionRule(action="Grant", permission="TRANSACTION:*")
perms.add(g)
admin._set_permissions(CURATOR_ROLE, permission_rules=perms)
admin._insert_user(name="TestUser", password="Password1!", status="ACTIVE")
admin._set_roles(username="TestUser", roles=[CURATOR_ROLE])
db.configure_connection(username="TestUser", password_method="plain",
password="Password1!")
# works
db.RecordType(name="TestRT1").insert()
db.Property(name="TestProp1", datatype=db.TEXT).insert()
# Deny TRANSACTION:INSERT
db.configure_connection()
perms = admin._get_permissions(CURATOR_ROLE)
g = admin.PermissionRule(action="Deny", permission=deny)
perms.add(g)
admin._set_permissions(CURATOR_ROLE, permission_rules=perms)
db.configure_connection(username="TestUser", password_method="plain",
password="Password1!")
# fails (in contrast to test_196a)
with pytest.raises(TransactionError) as cm:
# this should fail because the curator doesn't have TRANSACTION:INSERT:RECORDTYPE
db.RecordType(name="TestRT2").insert()
assert cm.value.errors[0].msg == "You are not allowed to do this."
# fails
with pytest.raises(TransactionError) as cm:
# this should fail because the curator doesn't have TRANSACTION:INSERT:PROPERTY
db.Property(name="TestProp2", datatype=db.TEXT).insert()
assert cm.value.errors[0].msg == "You are not allowed to do this."
@pytest.mark.parametrize("num", ["1e+23", "5e22", "2e-323", "2E-323", "5E22", "1E+23", "+1E+23"])
def test_143(num):
"""https://gitlab.com/caosdb/caosdb-server/-/issues/144"""
db.Property(name="scientific_notation", datatype=db.DOUBLE).insert()
db.RecordType(name="RT1").add_property("scientific_notation", value=num).insert()
for query in [
f"FIND RECORDTYPE RT1 WITH scientific_notation={num}",
f"FIND RECORDTYPE RT1 WITH scientific_notation='{num}'",
f"FIND RECORDTYPE RT1 WITH scientific_notation=\"{num}\"",
f"FIND RECORDTYPE RT1 WITH scientific_notation = {num}",
f"FIND RECORDTYPE RT1 WITH scientific_notation = '{num}'",
f"FIND RECORDTYPE RT1 WITH scientific_notation = \"{num}\""
]:
db.execute_query(query, unique=True)
@pytest.mark.parametrize("num", ["1 e+23", "- 5e22", "2e -323",
"2E- 323", "5 E 22", "1 E+ 23", "+ 1"])
def test_143_white_space(num):
"""https://gitlab.com/caosdb/caosdb-server/-/issues/144"""
for query in [
f"FIND RECORDTYPE RT1 WITH scientific_notation={num}",
f"FIND RECORDTYPE RT1 WITH scientific_notation='{num}'",
f"FIND RECORDTYPE RT1 WITH scientific_notation=\"{num}\"",
f"FIND RECORDTYPE RT1 WITH scientific_notation = {num}",
f"FIND RECORDTYPE RT1 WITH scientific_notation = '{num}'",
f"FIND RECORDTYPE RT1 WITH scientific_notation = \"{num}\""
]:
with pytest.raises(TransactionError) as cm:
db.execute_query(query)
assert cm.value.msg == f'You typed "{num}". Empty spaces are not allowed in numbers. Did you mean "{num.replace(" ", "")}"?'
def test_144():
"""https://gitlab.com/caosdb/caosdb-server/-/issues/144"""
db.Property(name="scientific_notation", datatype=db.DOUBLE, value="1e23").insert()
value = db.execute_query("FIND PROPERTY scientific_notation", unique=True).value
assert str(value) == "1e+23"
assert isinstance(value, float)
assert value == 1e23
assert value == 1e+23
def test_166():
"""https://gitlab.com/caosdb/caosdb-server/-/issues/166"""
db.RecordType(name="exists").insert()
db.Property(name="exists_property", datatype=db.INTEGER).insert()
db.RecordType(name="RT1").add_parent("exists").insert()
db.RecordType(name="RT2").add_parent("exists").add_property("exists_property", 32453).insert()
with pytest.raises(TransactionError) as cm:
db.Record(name="RT3").add_parent("notexists").insert()
assert [e.msg for e in cm.value.errors] == ["Entity has unqualified parents."]
with pytest.raises(TransactionError) as cm:
db.Record(name="RT4").add_parent("exists").add_property("notexists", 234243).insert()
assert [e.msg for e in cm.value.errors] == ["Entity has unqualified properties."]
with pytest.raises(TransactionError) as cm:
db.Record(
name="RT5").add_parent("notexists").add_property(
"exists_property",
234243).insert()
assert [e.msg for e in cm.value.errors] == ["Entity has unqualified parents."]
@pytest.mark.xfail(reason="fix needed")
def test_195():
"""https://gitlab.com/caosdb/caosdb-server/-/issues/195"""
admin._insert_role(name=CURATOR_ROLE, description="Desc")
perms = admin._get_permissions(CURATOR_ROLE)
g = admin.PermissionRule(action="Grant", permission="INVALID_PERMISSION:*")
perms.add(g)
with pytest.raises(Exception):
admin._set_permissions(CURATOR_ROLE, permission_rules=perms)
def test_216():
"""https://gitlab.com/caosdb/caosdb-server/-/issues/216"""
p1 = db.Property(name='p1', datatype=db.DOUBLE).insert()
cont = db.Container()
cont.append(db.RecordType(name="A")
.add_property(id=p1.id, name=p1.name, datatype=db.DOUBLE,
unit="min",
importance=db.RECOMMENDED)
.add_property(id=p1.id, name=p1.name,
importance=db.RECOMMENDED)
)
cont.append(db.RecordType(name="B")
.add_parent(name="A", inheritance=db.SUGGESTED))
cont.insert()
assert db.execute_query("FIND RECORDTYPE B", unique=True).name == "B"
def test_138():
"""Problems with non-integer ids in query filters, see
https://gitlab.com/caosdb/caosdb-server/-/issues/138
"""
queries = [
"FIND ENTITY WITH ID={}",
"FIND ENTITY WITH ID=None",
"FIND ENTITY WITH ID=\"1 non-existing id\""
]
for query in queries:
# No error, but of course also no results.
results = db.execute_query(query)
assert len(results) == 0
@pytest.mark.xfail(reason="Needs fix for parent name change caching, "
"see https://gitlab.com/caosdb/caosdb-server/-/issues/220")
def test_220():
"""Caching of children is not removed.
See https://gitlab.com/caosdb/caosdb-server/-/issues/220"""
rectype = db.RecordType(name="OldName").insert()
rec = db.Record(name="rec").add_parent(rectype).insert()
query = db.Query("FIND rec")
assert query.cached is None
res_1 = query.execute(unique=True)
assert query.cached is False, "First query should be uncached."
assert res_1.id == rec.id
res_2 = query.execute(unique=True)
assert query.cached is True, "Second query should be cached."
rectype.name = "NewName"
rectype.update()
res_3 = query.execute(unique=True)
assert res_3.parents[0].name == rectype.name, \
"The name of the record's parent should be up-to-date."
assert query.cached is False, "Query after name change of parent should not be cached."
@pytest.mark.xfail(reason="Needs fix for keeping datatype, "
"see https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/106")
def test_indiscale_106():
"""Datatype of old properties is changed.
See https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/106
"""
# Create TEXT Property
p = db.Property("prop", datatype=db.TEXT)
p.insert()
# Create Record using this Property
db.RecordType("RT").insert()
r = db.Record(name="rec")
r.add_parent("RT")
r.add_property(id=p.id, value="This is a TEXT property")
r.insert()
print(db.Record(id=r.id).retrieve())
assert db.Record(id=r.id).retrieve().get_property("prop").datatype == db.TEXT
# Changing Property's datatype to REFERENCE
p.datatype = db.REFERENCE
p.update()
# Existing Property should still be reported as TEXT
assert db.Record(id=r.id).retrieve().get_property("prop").datatype == db.TEXT
@pytest.mark.xfail(reason="https://gitlab.com/caosdb/caosdb-server/-/issues/235")
def test_235_long_name():
"""Should give an appropriate error, not just unknown server/-/issues."""
length = 10256
name = "N" * length
rt1 = db.RecordType(name=name)
try:
rt1.insert()
except Exception as exc:
assert not isinstance(exc, db.HTTPServerError)
# TODO more specific error should be asserted
rt2 = db.RecordType(name="Short")
rt2.insert()
rt2.name = name
try:
rt2.update()
except Exception as exc:
assert not isinstance(exc, db.HTTPServerError)
# TODO more specific error should be asserted