You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-4-lib/tests/vars/test_namespace.py

786 lines
27 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

import pytest
import os
from calculate.vars.datavars import Namespace, Variable, CyclicVariableError,\
VariableError, ReadonlyVariable,\
ChoiceVariable, IntegerVariable,\
StringVariable, DefaultValue,\
TableVariable, HashVariable,\
VariableNotFoundError
from calculate.vars.vars_loader import NamespaceIniFiller, VariableLoader,\
ProfileFiller, NamespaceIniFillerStrict
@pytest.mark.vars
class TestNamespace:
def test_init_empty_namespace(self):
ns = Namespace()
assert ns.childs == {}
assert ns.variables == {}
def test_create_variable(self):
ns = Namespace()
ns.addStringVariable("test", "12345")
assert ns.test.getValue() == "12345"
ns.addStringVariable("zxcv", "23456")
assert ns.zxcv.getValue() == "23456"
def test_create_ns_with_vars(self):
ns = Namespace()
ns.addNamespace(Namespace("os"))
ns.os.addStringVariable("test", "123")
ns.os.addNamespace(Namespace("linux"))
ns.os.linux.addStringVariable("shortname", "CLD")
assert ns.os.test.getValue() == "123"
assert ns.os["test"].getValue() == "123"
assert ns.os.linux.shortname.getValue() == "CLD"
assert ns.os.root == ns
def test_fill_namespace_simple(self):
ns = Namespace()
nsif = NamespaceIniFiller()
nsif.fill(ns, """
[os]
test = 123
[os][linux]
shortname = CLD
fullname = Calculate Linux Desktop
""")
assert ns.os.test.getValue() == "123"
assert ns.os.linux.shortname.getValue() == "CLD"
assert ns.os.linux.fullname.getValue() == "Calculate Linux Desktop"
assert ns.os.linux.root == ns
nsif.fill(ns, """
[os][linux]
shortname = CLDX
""")
assert ns.os.linux.shortname.getValue() == "CLDX"
assert ns.os.linux.fullname.getValue() == "Calculate Linux Desktop"
def test_fill_namespace_append_and_remove(self):
ns = Namespace()
nsif = NamespaceIniFiller()
nsif.fill(ns, """
[os]
test = 123
[os]
test += 345
""")
assert ns.os.test.getValue() == "123,345"
nsif.fill(ns, """
[os]
test -= 123
""")
assert ns.os.test.getValue() == "345"
nsif.fill(ns, """
[os]
test += asdf,qwer,zxcv
""")
assert ns.os.test.getValue() == "345,asdf,qwer,zxcv"
nsif.fill(ns, """
[os]
test -= asdf,zxcv
""")
assert ns.os.test.getValue() == "345,qwer"
def test_fill_namespace_clear_namespaces(self):
ns = Namespace()
nsif = NamespaceIniFiller()
nsif.fill(ns, """
[test][0]
dev = /dev/sda1
mount = swap
[test][1]
dev = /dev/sda2
mount = /
[test][2]
dev = /dev/sda5
mount = /var/calculate
""")
assert [x.dev.getValue() for x in ns.test] == ['/dev/sda1',
'/dev/sda2',
'/dev/sda5']
nsif.fill(ns, """
[test][0]
dev = /dev/sdb1
mount = swap
[test][1]
dev = /dev/sdb2
mount = /
""")
assert [x.dev.getValue() for x in ns.test] == ['/dev/sdb1',
'/dev/sdb2',
'/dev/sda5']
nsif.fill(ns, """
[test][]
[test][0]
dev = /dev/sdb1
mount = swap
[test][1]
dev = /dev/sdb2
mount = /
""")
assert [x.dev.getValue() for x in ns.test] == ['/dev/sdb1',
'/dev/sdb2']
def test_fill_namespace_strict_clear(self):
ns = Namespace()
nsif = NamespaceIniFiller()
nsif.fill(ns, """
[os][test][0]
dev = /dev/sda1
mount = swap
[os][test][1]
dev = /dev/sda2
mount = /
[os][test][2]
dev = /dev/sda5
mount = /var/calculate
[custom][test]
zxcv = 1
[custom][test2]
zxcv = 2
""")
assert ns.custom.test.zxcv.getValue() == "1"
assert ns.custom.test2.zxcv.getValue() == "2"
nsifs = NamespaceIniFillerStrict()
nsifs.fill(ns, """
[os][test][]
[custom][]
""")
assert [x for x in ns.custom] == []
def test_get_namespace_attrs(self):
ns = Namespace()
os = Namespace("os")
os.addStringVariable("test", "zxcv")
ns.addNamespace(os)
assert ns.os.test.getValue() == "zxcv"
assert ns.os["test"].getValue() == "zxcv"
assert "test" in ns.os
ns.os.test.setValue("123")
assert ns.os.test.getValue() == "123"
ns.os["test"].setValue("234")
assert ns.os.test.getValue() == "234"
def test_variable_get_value(self):
class TestVar(Variable):
def get(self):
return "A"
var = TestVar("test")
assert var.getValue() == "A"
def test_namespace_lookup(self):
ns = Namespace()
os = Namespace("os")
device = Namespace("device")
linux = Namespace("linux")
ns.addNamespace(os)
os.addNamespace(linux)
os.addNamespace(device)
device1 = device.addNamespace()
device1.addStringVariable("dev", "/dev/sda")
device2 = device.addNamespace()
device2.addStringVariable("dev", "/dev/sdb")
device3 = device.addNamespace()
device3.addStringVariable("dev", "/dev/sdc")
ns.addStringVariable("first", "first")
os.addStringVariable("second", "second")
linux.addStringVariable("third", "third")
assert ns.first.getValue() == "first"
assert ns.root.os.second.getValue() == "second"
assert ns.os.second.getValue() == "second"
assert os.root.os.second.getValue() == "second"
assert os.second.getValue() == "second"
assert linux.third.getValue() == "third"
assert linux.root.os.second.getValue() == "second"
with pytest.raises(VariableNotFoundError):
os.third
assert ns.os.device[0].dev.getValue() == "/dev/sda"
assert ns.os.device["0"].dev.getValue() == "/dev/sda"
assert ns.os.device[1].dev.getValue() == "/dev/sdb"
assert ns.os.device[2].dev.getValue() == "/dev/sdc"
assert ns.os.device.parent.second.getValue() == "second"
assert ns.os.device.parent.parent.os.second.getValue() == "second"
assert ns.os.device.parent.parent.parent.os.second.\
getValue() == "second"
def test_variable_get_value_by_variable(self):
class TestVar1(Variable):
def get(self):
return "%s,B" % self.vars.test2.getValue(self)
class TestVar2(Variable):
def get(self):
return "A"
ns = Namespace()
ns.addVariable(TestVar1("test1"))
ns.addVariable(TestVar2("test2"))
assert ns.test1.getValue() == "A,B"
def test_variable_get_value_by_changed_variable(self):
class TestVar1(Variable):
counter = 0
def get(self):
self.counter += 1
return "%s,B" % self.vars.test2.getValue(self)
ns = Namespace()
test1 = TestVar1("test1")
ns.addVariable(test1)
ns.addStringVariable("test2", "A")
assert ns.test1.getValue() == "A,B"
assert test1.counter == 1
# test for get cached variable value
assert ns.test1.getValue() == "A,B"
assert test1.counter == 1
# change value of test2 for recalculate test1
ns.test2.setValue("C")
assert ns.test1.getValue() == "C,B"
assert test1.counter == 2
# change value of test2 for recalculate test1
ns.test2.setValue("D")
assert ns.test1.getValue() == "D,B"
assert test1.counter == 3
def test_cyclic_variable(self):
class TestVar1(Variable):
def get(self):
return "%s,test1" % self.vars.test2.getValue(self)
class TestVar2(Variable):
def get(self):
return "%s,test2" % self.vars.test3.getValue(self)
class TestVar3(Variable):
def get(self):
return "%s,test3" % self.vars.test1.getValue(self)
test1 = TestVar1("test1")
test2 = TestVar2("test2")
test3 = TestVar3("test3")
ns = Namespace()
ns.addVariable(test1)
ns.addVariable(test2)
ns.addVariable(test3)
with pytest.raises(CyclicVariableError) as e:
ns.test1.getValue()
assert e.value.queue[:-1] == ("test1", "test2", "test3")
with pytest.raises(VariableError) as e:
ns.test1.getValue()
def test_drop_invalidate_after_set_value(self):
class TestVar1(Variable):
counter = 0
def get(self):
self.counter += 1
return "%s,test1" % self.vars.test2.getValue(self)
class TestVar2(Variable):
def get(self):
return "ZZZZ"
test1 = TestVar1("test1")
test2 = TestVar2("test2")
ns = Namespace()
ns.addVariable(test1)
ns.addVariable(test2)
assert test1.getValue() == "ZZZZ,test1"
test1.setValue("VVVV")
assert test1.getValue() == "VVVV"
assert test1.counter == 1
test2.setValue("XXXX")
assert test1.getValue() == "VVVV"
assert test1.counter == 1
test1.invalidate()
assert test1.getValue() == "XXXX,test1"
assert test1.counter == 2
def test_change_invalidator_variable(self):
class VarTest(Variable):
counter = 0
def get(self):
self.counter += 1
if self.vars.ifvar.getValue(self):
return "%s,test1" % self.vars.vara.getValue(self)
else:
return "%s,test1" % self.vars.varb.getValue(self)
vartest = VarTest("vartest")
ns = Namespace()
ns.addVariable(vartest)
ns.addStringVariable("vara", "vara")
ns.addStringVariable("varb", "varb")
ns.addStringVariable("ifvar", "true")
assert vartest.getValue() == "vara,test1"
assert vartest.counter == 1
ns.vara.setValue("varc")
assert vartest.getValue() == "varc,test1"
assert vartest.counter == 2
ns.ifvar.setValue("")
assert vartest.getValue() == "varb,test1"
assert vartest.counter == 3
ns.vara.setValue("vard")
assert vartest.getValue() == "varb,test1"
assert vartest.counter == 3
def test_readonly_varaible(self):
class TestVar1(Variable):
properties = [ReadonlyVariable, StringVariable]
def get(self):
return "test1"
test1 = TestVar1("test1")
assert test1.getValue() == "test1"
with pytest.raises(VariableError):
test1.setValue("test2")
assert test1.getValue() == "test1"
test1.setValue("test2", force=True)
assert test1.getValue() == "test2"
def test_choice_variable(self):
class TestVar1(Variable):
properties = [ChoiceVariable]
def choice(self):
return ["test1", "test2"]
test1 = TestVar1("test1")
with pytest.raises(VariableError):
test1.setValue("test3")
test1.setValue("test2")
assert test1.getValue() == "test2"
def test_integer_variable(self):
class TestVar1(Variable):
properties = [IntegerVariable]
test1 = TestVar1("test1")
with pytest.raises(VariableError):
test1.setValue("test3")
test1.setValue("33")
assert test1.getValue() == 33
test1.setValue("-33")
assert test1.getValue() == -33
def test_default_value_property(self):
class TestVar1(Variable):
def get(self):
return "123"
test1 = TestVar1("test1")
assert test1.getValue() == "123"
test1.setValue("987")
test1.addProperty(DefaultValue("567"))
assert test1.getValue() == "987"
test1.invalidate()
assert test1.getValue() == "567"
def test_get_comment(self):
class TestVar1(Variable):
def get(self):
return "123"
class TestVar2(Variable):
def get(self):
return "234"
def getComment(self):
return "[%s]" % self.getValue()
class TestVar3(Variable):
def get(self):
return "ZXC %s" % self.vars.test2.getCommentValue(self)
ns = Namespace()
test1 = TestVar1("test1")
assert test1.getValue() == "123"
assert test1.getComment() == "123"
test2 = TestVar2("test2")
assert test2.getValue() == "234"
assert test2.getComment() == "[234]"
test3 = TestVar3("test3")
ns.addVariable(test1)
ns.addVariable(test2)
ns.addVariable(test3)
assert test3.getValue() == "ZXC [234]"
test2.setValue("567")
assert test3.getValue() == "ZXC [567]"
def test_wrong_choice_varaible(self):
class TestVar1(Variable):
properties = [ChoiceVariable]
class TestVar2(Variable):
properties = [ChoiceVariable]
def choice(self):
return ["test1", "test2"]
class TestVar3(Variable):
properties = [ChoiceVariable]
def choiceComment(self):
return [("test1", "Test1"),
("test2", "Test2")]
test1 = TestVar1("test1")
test2 = TestVar2("test2")
test3 = TestVar3("test3")
with pytest.raises(VariableError):
test1.choice()
with pytest.raises(VariableError):
test1.choiceComment()
assert test2.choice() == ["test1", "test2"]
assert test2.choiceComment() == [("test1", "test1"),
("test2", "test2")]
assert test3.choice() == ["test1", "test2"]
assert test3.choiceComment() == [("test1", "Test1"),
("test2", "Test2")]
def test_loading_test_variable_module(self):
ns = Namespace()
vl = VariableLoader()
vl.fill(ns, "tests/vars/variables", "testvars")
assert ns.level.simple.getValue() == "simple value"
assert ns.level.uselocalsimple.getValue() == "Using simple value"
assert ns.level.usefullsimple.getValue() == "Using simple value"
with pytest.raises(VariableError):
ns.level.badchoice.choice()
with pytest.raises(VariableError):
ns.level.badchoice.choiceComment()
assert ns.level.simple_choice.choice() == ["/dev/sda1",
"/dev/sda2",
"/dev/sda3"]
assert ns.level.comment_choice.choice() == ["/dev/sda1",
"/dev/sda2",
"/dev/sda3"]
assert ns.level.comment_choice.choiceComment() == [
("/dev/sda1", "SWAP"),
("/dev/sda2", "ROOT"),
("/dev/sda3", "DATA")]
ns.level.disks.setValue(["/dev/sda2", "/dev/sda1"])
assert ns.level.disks.getValue() == ["/dev/sda2", "/dev/sda1"]
assert ns.level.comment_choice.choice() == ["/dev/sda2", "/dev/sda1"]
assert ns.level.comment_choice.choiceComment() == [
("/dev/sda2", "ROOT"),
("/dev/sda1", "SWAP")]
assert ns.level is not ns.level.level2.root
assert ns is ns.level.level2.root
assert ns.level.level2.vargetter.getValue() == "/ test"
def test_hash_variable(self):
# hash variable
ns = Namespace()
vl = VariableLoader()
vl.fill(ns, "tests/vars/variables", "testvars")
assert ns.level.linux.getFullname() == "level.linux"
assert ns.level.linux.ver.fullname == "level.linux.ver"
assert ns.level.linux.ver.getValue() == "1.0"
assert ns.level.linux.shortname.getValue() == "CLD"
# проверка обновления значения hash переменной при обновлении
# значения у зависимой перемнной
ns.level.version.setValue("2.0")
assert ns.level.linux.ver.getValue() == "2.0"
# проверка установки значения hash переменной
ns.level.linux.ver.setValue("3.0")
assert ns.level.linux.ver.getValue() == "3.0"
# после установки хотя бы одного значения в hash переменной
# обновление остальных прекращаются до инвалидации (так как
# значения рассматриваются комплексно)
ns.level.myshortname.setValue("CLDG")
assert ns.level.linux.shortname.getValue() == "CLD"
# проверка попытки изменить readonly переменную
with pytest.raises(VariableError):
ns.level.linux.shortname.setValue("CLDX")
# проверка сбора значения hash перемнной
ns.level.linux.invalidate()
assert ns.level.linux.ver.getValue() == "2.0"
assert ns.level.linux.shortname.getValue() == "CLDG"
assert ns.level.linux.test.getValue() == "my test - 2.0"
# проверка обновления значения переменной, используеющей одно
# из значений hash переменной
assert ns.level.shortname_test.getValue() == "CLDG test"
ns.level.linux.shortname.setValue("CLDX", force=True)
assert ns.level.shortname_test.getValue() == "CLDX test"
def test_table_variable(self):
# table variable
ns = Namespace()
vl = VariableLoader()
vl.fill(ns, "tests/vars/variables", "testvars")
assert ns.level.device[0].dev.getValue() == "/dev/sda"
assert ns.level.device[1].dev.getValue() == "/dev/sdb"
assert ns.level.device.getValue() == [{"dev": "/dev/sda",
"type": "hdd",
"name": "Samsung SSD"},
{"dev": "/dev/sdb",
"type": "flash",
"name": "Transcend 64GB"}]
assert ns.level.device[1].type.getValue() == "flash"
# проверка обновления списка пространства имён у табличной переменной
ns.level.devicelist.setValue(["/dev/sda", "/dev/sdb", "/dev/sdc"])
assert ns.level.device[2].type.getValue() == "usbhdd"
assert [x.type.getValue() for x in ns.level.device] == ["hdd",
"flash",
"usbhdd"]
assert ns.level.device_child.getValue() == "hdd"
ns.level.devicelist.setValue(["/dev/sda", "/dev/sdb"])
ns.level.device[0].type.setValue("flash")
assert ns.level.device.getValue() == [{"dev": "/dev/sda",
"type": "flash",
"name": "Samsung SSD"},
{"dev": "/dev/sdb",
"type": "flash",
"name": "Transcend 64GB"}]
assert ns.level.device_child.getValue() == "flash"
# после установки хотя бы одного значения в table переменной
# обновление остальных прекращаются до инвалидации (так как
# значения рассматриваются комплексно)
ns.level.devicelist.setValue(["/dev/sda", "/dev/sdb", "/dev/sdc"])
assert [x.dev.getValue() for x in ns.level.device] == ["/dev/sda",
"/dev/sdb"]
ns.level.device.invalidate()
assert [x.dev.getValue() for x in ns.level.device] == ["/dev/sda",
"/dev/sdb",
"/dev/sdc"]
# проверить на повторное изменение, убедится, что _drop_child
# отрабатывает
ns.level.devicelist.setValue(["/dev/sda", "/dev/sdb",
"/dev/sdc", "/dev/sdd"])
ns.level.device.invalidate()
assert [x.dev.getValue() for x in ns.level.device] == ["/dev/sda",
"/dev/sdb",
"/dev/sdc",
"/dev/sdd"]
def test_wrong_table_variable(self):
class Testtable(TableVariable):
class Data(TableVariable.Data):
def get(self):
return [{'dev': '123', 'name': '098'}]
ns = Namespace()
ns.addNamespace(Namespace("test"))
ns.test.addNamespace(Namespace("test2"))
error_message = ("Missed 'hash_vars' attribute for table "
"variable test.test2.testtable")
with pytest.raises(VariableError) as e:
ns.test.test2.addNamespace(Testtable("testtable", ns.test.test2))
assert str(e.value) == error_message
def test_wrong_hash_variable(self):
class Testhash(HashVariable):
class Data(HashVariable.Data):
def get(self):
return {'dev': '123', 'name': '098'}
ns = Namespace()
ns.addNamespace(Namespace("test"))
ns.test.addNamespace(Namespace("test2"))
error_message = ("Missed 'hash_vars' attribute for hash "
"variable test.test2.testhash")
with pytest.raises(VariableError) as e:
ns.test.test2.addNamespace(Testhash("testhash", ns.test.test2))
assert str(e.value) == error_message
def test_namespace_iteration(self):
ns = Namespace()
ns0 = ns.addNamespace()
ns0.addStringVariable("test", "123")
ns1 = ns.addNamespace()
ns1.addStringVariable("test", "234")
ns2 = ns.addNamespace()
ns2.addStringVariable("test", "456")
assert [x.test.getValue() for x in ns] == ["123", "234", "456"]
def test_subnamespace(self):
ns = Namespace()
vl = VariableLoader()
vl.fill(ns, "tests/vars/variables", "testvars")
assert ns.level.level3.my_var1.getValue() == "testing"
assert ns.level.level3.myvar2.getValue() == "testing2"
def test_variable_not_found(self):
ns = Namespace()
vl = VariableLoader()
vl.fill(ns, "tests/vars/variables", "testvars")
error_message = "Variable or namespace level.level3.myvar3 not found"
with pytest.raises(VariableError) as e:
ns.level.level3.myvar3.getValue()
assert str(e.value) == error_message
# TODO: тест использует значения на конкретной машине
# def test_simple(self):
# ns = Namespace()
# vl = VariableLoader()
# vl.fill(ns, *VariableLoader.default())
# # нужно исправить тест, так
# # assert [x.name.getValue() for x in ns.os.gentoo.repositories] ==\
# ["gentoo","distros","calculate","custom"]
# assert ns.os.gentoo.make_profile.getValue() ==\
# "/etc/portage/make.profile"
# assert ns.os.gentoo.profile.path.getValue() ==\
# "/var/db/repos/distros/profiles/CLD/amd64/20"
# assert ns.os.gentoo.profile.name.getValue() == "distros:CLD/amd64/20"
def test_profile_filler(self):
ns = Namespace()
vl = VariableLoader()
vl.fill(ns, "tests/vars/variables", "testvars")
class ProfileFillerTest(ProfileFiller):
def getRepositoryMap(self, ns):
curdir = os.getcwd()
return {'distros':
os.path.join(curdir,
"tests/utils/gentoo/repos/distros"),
'calculate':
os.path.join(curdir,
"tests/utils/gentoo/repos/calculate"),
'gentoo':
os.path.join(curdir,
"tests/utils/gentoo/portage")}
assert ns.os.hashvar.value1.getValue() == "test1"
assert ns.os.hashvar.value2.getValue() == "test2"
assert ns.os.tablevar[0].dev.getValue() == "/dev/sdb1"
assert ns.os.tablevar[1].dev.getValue() == "/dev/sdb2"
pf = ProfileFillerTest()
pf.fill(ns, "tests/utils/gentoo/repos/distros/profiles/CLD/amd64")
assert ns.os.linux.test.getValue() == "test"
assert ns.os.linux.arch.getValue() == "amd64"
assert ns.os.linux.title.getValue() == "Calculate Linux Desktop KDE 20"
# Hash
assert ns.os.hashvar.value1.getValue() == "20"
assert ns.os.hashvar.value2.getValue() == "30"
ns.os.hashvar.value1.setValue("40")
assert ns.os.hashvar.value1.getValue() == "40"
ns.os.hashvar.value1.invalidate()
assert ns.os.hashvar.value1.getValue() == "20"
# Table
assert ns.os.tablevar[0].dev.getValue() == "/dev/sda1"
assert ns.os.tablevar[1].dev.getValue() == "/dev/sda2"
assert ns.os.tablevar[2].dev.getValue() == "/dev/sda5"
ns.os.tablevar[0].dev.invalidate()
assert ns.os.tablevar[0].dev.getValue() == "/dev/sda1"
assert ns.os.tablevar[1].dev.getValue() == "/dev/sda2"
assert ns.os.tablevar[2].dev.getValue() == "/dev/sda5"
def test_fill_namespace_by_module(self):
pass
# ns = Namespace()
# vl = VariableLoader()
# vl.fill(ns, *VariableLoader.default())
# assert "os" in ns
# assert "config" in ns.os.gentoo
# assert "main" in ns
# assert ns.os.gentoo.config.getValue() is not None