def __get_jmx_shorthands(self, configs): """ Generate json file with execution, executor and scenario settings :type configs: list :return: list """ jmxes = [] for filename in configs[:]: if filename.lower().endswith(".jmx"): jmxes.append(filename) configs.remove(filename) if jmxes: self.log.debug("Adding JMX shorthand config for: %s", jmxes) fds, fname = tempfile.mkstemp(".json", "jmxes_", dir=self.engine.artifacts_base_dir) os.close(fds) config = Configuration() for jmx_file in jmxes: config.get("execution", []).append({"executor": "jmeter", "scenario": {"script": jmx_file}}) config.dump(fname, Configuration.JSON) return [fname] else: return []
def test_merge(self): obj = Configuration() configs = [ RESOURCES_DIR + "yaml/test.yml", RESOURCES_DIR + "json/merge1.json", RESOURCES_DIR + "json/merge2.json", ] obj.load(configs) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.JSON) with open(fname) as fh: ROOT_LOGGER.debug("JSON:\n%s", fh.read()) jmeter = obj['modules']['jmeter'] classval = jmeter['class'] self.assertEquals("bzt.modules.jmeter.JMeterExecutor", classval) self.assertEquals("value", obj['key']) self.assertEquals(6, len(obj["list-append"])) self.assertEquals(2, len(obj["list-replace"])) self.assertEquals(2, len(obj["list-replace-notexistent"])) self.assertIsInstance(obj["list-complex"][1][0], BetterDict) self.assertIsInstance(obj["list-complex"][1][0], BetterDict) self.assertIsInstance(obj["list-complex"][1][0], BetterDict) self.assertFalse("properties" in jmeter) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.JSON) checker = Configuration() checker.load([fname]) token = checker["list-complex"][1][0]['token'] self.assertNotEquals('test', token) token_orig = obj["list-complex"][1][0]['token'] self.assertEquals('test', token_orig)
def __get_jmx_shorthands(self, configs): """ Generate json file with execution, executor and scenario settings :type configs: list :return: list """ jmxes = [] for filename in configs[:]: if filename.lower().endswith(".jmx"): jmxes.append(filename) configs.remove(filename) if jmxes: self.log.debug("Adding JMX shorthand config for: %s", jmxes) fds = NamedTemporaryFile(prefix="jmx_", suffix=".json") fname = fds.name fds.close() config = Configuration() for jmx_file in jmxes: config.get(ScenarioExecutor.EXEC, []).append({"executor": "jmeter", "scenario": jmx_file}) config.dump(fname, Configuration.JSON) return [fname] else: return []
def process(self): output_format = Configuration.JSON if self.options.json else Configuration.YAML self.log.info('Loading Swagger spec %s', self.file_to_convert) self.file_to_convert = os.path.abspath(os.path.expanduser(self.file_to_convert)) if not os.path.exists(self.file_to_convert): raise TaurusInternalException("File does not exist: %s" % self.file_to_convert) self.converter = SwaggerConverter(self.log) try: converted_config = self.converter.convert(self.file_to_convert) except BaseException: self.log.error("Error while processing Swagger spec: %s", self.file_to_convert) raise exporter = Configuration() exporter.merge(converted_config) if self.options.file_name: file_name = self.options.file_name else: file_name = self.file_to_convert + "." + output_format.lower() exporter.dump(file_name, output_format) self.log.info("Done processing, result saved in %s", file_name)
def __get_jtl_shorthands(self, configs): """ Generate json file with execution, executor and scenario settings :type configs: list :return: list """ jtls = [] for filename in configs[:]: if filename.lower().endswith(".jtl"): jtls.append(filename) configs.remove(filename) if jtls: self.log.debug("Adding JTL shorthand config for: %s", jtls) fds = NamedTemporaryFile(prefix="jtl_", suffix=".json") fname = fds.name fds.close() config = Configuration() for jtl in jtls: piece = BetterDict.from_dict({"executor": "external-results-loader", "data-file": jtl}) config.get(ScenarioExecutor.EXEC, [], force_set=True).append(piece) config.dump(fname, Configuration.JSON) return [fname] else: return []
def process(self): """ Process file :return: """ output_format = Configuration.JSON if self.options.json else Configuration.YAML self.log.info('Loading jmx file %s', self.file_to_convert) self.file_to_convert = os.path.abspath(os.path.expanduser(self.file_to_convert)) if not os.path.exists(self.file_to_convert): self.log.error("File %s does not exist", self.file_to_convert) raise RuntimeError("File does not exist: %s" % self.file_to_convert) self.converter = Converter(self.log) try: jmx_as_dict = self.converter.convert(self.file_to_convert, self.options.dump_jmx) except BaseException: self.log.error("Error while processing jmx file: %s", self.file_to_convert) raise exporter = Configuration() exporter.merge(jmx_as_dict) if self.options.file_name: file_name = self.options.file_name else: file_name = self.file_to_convert + "." + output_format.lower() exporter.dump(file_name, output_format) self.log.info("Done processing, result saved in %s", file_name)
def test_filtering(self): obj = Configuration() obj.merge({ "drop": "me", "also-drop": {"this": "drop"}, "and-also-drop": ["thelist"], "but-keep": "value", "and-also-keep": { "nested": "value", "while-dropping": "some" }, "filter-subitems": { "keep": "value", "drop": "some" } }) rules = { "but-keep": True, "and-also-keep": {"nested": True}, "!filter-subitems": {"drop": True}, } obj.filter(rules) expected = { "but-keep": "value", "and-also-keep": {"nested": "value"}, "filter-subitems": {"keep": "value"}, } self.assertEquals(expected, obj)
def test_unicode(self): obj = Configuration() expected = six.u("Юникод") obj.merge({ "ustr": expected, }) ustr = obj.get("ustr", "nope") self.assertEqual(ustr, expected)
def test_merge_removal(self): obj = Configuration() obj.merge({ "foo": "bar", }) obj.merge({ "^foo": "baz", }) self.assertNotIn("foo", obj)
def test_merge_overwrite(self): obj = Configuration() obj.merge({ "foo": {"bar": "baz"}, }) obj.merge({ "~foo": "baz", }) self.assertEqual(obj["foo"], "baz")
def test_overwrite_execution_locations(self): obj = Configuration() obj.merge({ "execution": [{"locations": {"us-central1-a": 1}}], }) obj.merge({ "$execution": [{"~locations": {"harbor-1": 1}}], }) ROOT_LOGGER.info(obj) self.assertEqual(obj, {"execution": [{"locations": {"harbor-1": 1}}]})
def test_save(self): obj = Configuration() obj.merge({ "str": "text", "uc": six.u("ucstring") }) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.YAML) with open(fname) as fh: written = fh.read() ROOT_LOGGER.debug("YAML:\n%s", written) self.assertNotIn("unicode", written)
def test_encode_decode_infinities(self): engine = EngineEmul() obj = Configuration() obj.merge({ "foo": float("inf"), }) cfg = engine.create_artifact("config", ".json") obj.dump(cfg, Configuration.JSON) with open(cfg) as fds: dump = json.loads(fds.read()) self.assertEqual(dump["foo"], "inf") self.assertEqual(dehumanize_time(dump["foo"]), float("inf"))
def test_elementwise_merge(self): obj = Configuration() obj.merge({ "execution": [{ "executor": "jmeter", "iterations": 10, }], }) obj.merge({ "$execution": [{"iterations": 20}], }) self.assertEqual(obj["execution"][0]["iterations"], 20)
def test_masq_sensitive(self): obj = Configuration() obj.merge({ "token": "my-precious", "my_password": "******", "secret": "secret", "secret_story": "story", }) BetterDict.traverse(obj, Configuration.masq_sensitive) self.assertEquals(obj["token"], "*" * 8) self.assertEquals(obj["my_password"], "*" * 8) self.assertEquals(obj["secret"], "*" * 8) self.assertEquals(obj["secret_story"], "story")
def process(self): output_format = Configuration.JSON if self.options.json else Configuration.YAML self.log.info('Loading SoapUI project %s', self.file_to_convert) self.file_to_convert = os.path.abspath(os.path.expanduser(self.file_to_convert)) if not os.path.exists(self.file_to_convert): raise TaurusInternalException("File does not exist: %s" % self.file_to_convert) self.converter = SoapUIScriptConverter(self.log) try: converted_config = self.converter.convert_script(self.file_to_convert, self.options.test_case) except BaseException: self.log.error("Error while processing SoapUI project: %s", self.file_to_convert) raise self._cleanup_config(converted_config) exporter = Configuration.from_dict(converted_config) if self.options.file_name: file_name = self.options.file_name else: file_name = self.file_to_convert + "." + output_format.lower() exporter.dump(file_name, output_format) self.log.info("Done processing, result saved in %s", file_name)
def __get_jtl_shorthands(self, configs): """ Generate json file with execution, executor and scenario settings :type configs: list :return: list """ jtls = [] for filename in configs[:]: if filename.lower().endswith(".jtl"): jtls.append(filename) configs.remove(filename) if jtls: self.log.debug("Adding JTL shorthand config for: %s", jtls) fds = NamedTemporaryFile(prefix="jtl_", suffix=".json") fname = fds.name fds.close() config = Configuration() for jtl in jtls: piece = BetterDict.from_dict({ "executor": "external-results-loader", "data-file": jtl }) config.get(EXEC, [], force_set=True).append(piece) config.dump(fname, Configuration.JSON) return [fname] else: return []
def test_tabs(self): obj = Configuration() obj.tab_replacement_spaces = 4 obj.load([RESOURCES_DIR + "yaml/tabs-issue.yml"]) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.YAML) self.assertFilesEqual(RESOURCES_DIR + "yaml/tabs-issue-spaces.yml", fname)
def __get_jmx_shorthands(self, configs): """ Generate json file with execution, executor and scenario settings :type configs: list :return: list """ jmxes = [] for filename in configs[:]: if filename.lower().endswith(".jmx"): jmxes.append(filename) configs.remove(filename) if jmxes: self.log.debug("Adding JMX shorthand config for: %s", jmxes) fds = NamedTemporaryFile(prefix="jmx_", suffix=".json") fname = fds.name fds.close() config = Configuration() for jmx_file in jmxes: piece = BetterDict.from_dict({ "executor": "jmeter", "scenario": { "script": jmx_file } }) config.get(EXEC, [], force_set=True).append( piece) # Does it brake single execution? config.dump(fname, Configuration.JSON) return [fname] else: return []
def test_save(self): obj = Configuration() obj.merge({"str": "text", "uc": six.u("ucstring")}) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.YAML) with open(fname) as fh: written = fh.read() logging.debug("YAML:\n%s", written) self.assertNotIn("unicode", written)
def test_load(self): obj = Configuration() configs = [ __dir__() + "/../bzt/10-base.json", __dir__() + "/json/jmx.json", __dir__() + "/json/concurrency.json" ] obj.load(configs) logging.debug("config:\n%s", obj) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.JSON) with open(fname) as fh: logging.debug("JSON:\n%s", fh.read()) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.YAML) with open(fname) as fh: logging.debug("YAML:\n%s", fh.read()) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.INI) with open(fname) as fh: logging.debug("INI:\n%s", fh.read())
def test_load(self): obj = Configuration() configs = [ BASE_CONFIG, RESOURCES_DIR + "json/jmx.json", RESOURCES_DIR + "json/concurrency.json" ] obj.load(configs) logging.debug("config:\n%s", obj) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.JSON) with open(fname) as fh: logging.debug("JSON:\n%s", fh.read()) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.YAML) with open(fname) as fh: logging.debug("YAML:\n%s", fh.read())
def test_filtering(self): obj = Configuration() obj.merge({ "drop": "me", "also-drop": {"this": "drop"}, "and-also-drop": ["thelist"], "but-keep": "value", "and-also-keep": { "nested": "value", "while-dropping": "some" } }) obj.filter({"but-keep": True, "and-also-keep": {"nested": True}}) self.assertEquals({"and-also-keep": {"nested": "value"}, "but-keep": "value"}, obj)
def test_load(self): obj = Configuration() configs = [ BASE_CONFIG, RESOURCES_DIR + "json/jmx.json", RESOURCES_DIR + "json/concurrency.json" ] obj.load(configs) ROOT_LOGGER.debug("config:\n%s", obj) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.JSON) with open(fname) as fh: ROOT_LOGGER.debug("JSON:\n%s", fh.read()) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.YAML) with open(fname) as fh: ROOT_LOGGER.debug("YAML:\n%s", fh.read())
def test_filtering(self): obj = Configuration() obj.merge({ "drop": "me", "also-drop": { "this": "drop" }, "and-also-drop": ["thelist"], "but-keep": "value", "and-also-keep": { "nested": "value", "while-dropping": "some" }, "filter-subitems": { "keep": "value", "drop": "some" } }) rules = { "but-keep": True, "and-also-keep": { "nested": True }, "!filter-subitems": { "drop": True }, } obj.filter(rules) expected = { "but-keep": "value", "and-also-keep": { "nested": "value" }, "filter-subitems": { "keep": "value" }, } self.assertEquals(expected, obj)
def __get_jmx_shorthands(self, configs): """ Generate json file with execution, executor and scenario settings :type configs: list :return: list """ jmxes = [] for filename in configs[:]: if filename.lower().endswith(".jmx"): jmxes.append(filename) configs.remove(filename) if jmxes: self.log.debug("Adding JMX shorthand config for: %s", jmxes) fds, fname = tempfile.mkstemp(".json", "jmxes_", dir=self.engine.artifacts_base_dir) os.close(fds) config = Configuration() for jmx_file in jmxes: config.get("execution", []).append({ "executor": "jmeter", "scenario": { "script": jmx_file } }) config.dump(fname, Configuration.JSON) return [fname] else: return []
def setUp(self): self.obj = ConfigOverrider(logging.getLogger()) self.config = Configuration()
class TestConfigOverrider(BZTestCase): def setUp(self): self.obj = ConfigOverrider(logging.getLogger()) self.config = Configuration() def test_numbers(self): self.obj.apply_overrides(["int=11", "float=3.14"], self.config) self.assertEqual(self.config.get("int"), int(11)) self.assertEqual(self.config.get("float"), float(3.14)) def test_booleans(self): self.obj.apply_overrides(["yes=true", "no=false"], self.config) self.assertEqual(self.config.get("yes"), bool(True)) self.assertEqual(self.config.get("no"), bool(False)) def test_strings(self): self.obj.apply_overrides([ "plain=ima plain string", """quoted='"ima quoted string"'""", """empty-quoted='""'""", '''escaped="a "b" 'c' d"''', '''escaped-quoted="a "b" 'c' d"''' ], self.config) self.assertEqual(self.config.get("plain"), str("ima plain string")) self.assertEqual(self.config.get("quoted"), str('''"ima quoted string"''')) self.assertEqual(self.config.get("empty-quoted"), str('""')) self.assertEqual(self.config.get("escaped"), str('''"a "b" 'c' d"''')) self.assertEqual(self.config.get("escaped-quoted"), str('''"a "b" 'c' d"''')) def test_strings_literals_clash(self): # we want to pass literal string 'true' (and not have it converted to bool(True)) self.obj.apply_overrides(['yes="true"', 'list="[1,2,3]"'], self.config) self.assertEqual(self.config.get("yes"), str("true")) self.assertEqual(self.config.get("list"), str("[1,2,3]")) def test_null(self): self.obj.apply_overrides(['nothing=null'], self.config) self.assertEqual(self.config.get("nothing"), None) def test_objects(self): self.config.merge({ "obj": { "key": "142857", }, }) self.obj.apply_overrides(['obj={"key": "value"}'], self.config) self.assertEqual(self.config.get("obj").get("key"), str("value")) def test_lists(self): self.config.merge({ "list": ["stuff"], }) self.obj.apply_overrides(['list=[1, 2.0, "str", []]'], self.config) self.assertEqual(self.config.get("list"), list([1, 2.0, "str", []])) def test_nested_quotation(self): # bzt -o man='{"name": "Robert \"Destroyer of Worlds\" Oppenheimer"}' self.obj.apply_overrides([ '''man={"name": "Robert \\"Destroyer of Worlds\\" Oppenheimer"}''' ], self.config) self.assertEqual( self.config.get("man").get("name"), str('Robert "Destroyer of Worlds" Oppenheimer')) def test_no_override(self): self.obj.apply_overrides(['nothing='], self.config) self.assertEqual(self.config.get("nothing"), None) def test_unquoted_keys(self): self.obj.apply_overrides(['obj={abc: def}'], self.config) self.assertEqual(self.config.get("obj").get("abc"), str("def"))
def get_token(): a = Configuration() a.load([os.path.expanduser("~/.bzt-rc")]) return a['modules']['blazemeter']['token']
def test_merge(self): obj = Configuration() configs = [ __dir__() + "/resources/yaml/test.yml", __dir__() + "/resources/json/merge1.json", __dir__() + "/resources/json/merge2.json", ] obj.load(configs) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.JSON) with open(fname) as fh: logging.debug("JSON:\n%s", fh.read()) jmeter = obj['modules']['jmeter'] classval = jmeter['class'] self.assertEquals("bzt.modules.jmeter.JMeterExecutor", classval) self.assertEquals("value", obj['key']) self.assertEquals(6, len(obj["list-append"])) self.assertEquals(2, len(obj["list-replace"])) self.assertEquals(2, len(obj["list-replace-notexistent"])) self.assertIsInstance(obj["list-complex"][1][0], BetterDict) self.assertIsInstance(obj["list-complex"][1][0], BetterDict) self.assertIsInstance(obj["list-complex"][1][0], BetterDict) self.assertFalse("properties" in jmeter) fname = tempfile.mkstemp()[1] obj.dump(fname, Configuration.JSON) checker = Configuration() checker.load([fname]) token = checker["list-complex"][1][0]['token'] self.assertNotEquals('test', token) token_orig = obj["list-complex"][1][0]['token'] self.assertEquals('test', token_orig)
class TestConfigOverrider(BZTestCase): def setUp(self): super(TestConfigOverrider, self).setUp() self.obj = ConfigOverrider(logging.getLogger()) self.config = Configuration() def test_numbers(self): self.obj.apply_overrides(["int=11", "float=3.14"], self.config) self.assertEqual(self.config.get("int"), int(11)) self.assertEqual(self.config.get("float"), float(3.14)) def test_booleans(self): self.obj.apply_overrides(["yes=true", "no=false"], self.config) self.assertEqual(self.config.get("yes"), bool(True)) self.assertEqual(self.config.get("no"), bool(False)) def test_strings(self): self.obj.apply_overrides(["plain=ima plain string", """quoted='"ima quoted string"'""", """empty-quoted='""'""", '''escaped="a "b" 'c' d"''', '''escaped-quoted="a "b" 'c' d"'''], self.config) self.assertEqual(self.config.get("plain"), str("ima plain string")) self.assertEqual(self.config.get("quoted"), str('''"ima quoted string"''')) self.assertEqual(self.config.get("empty-quoted"), str('""')) self.assertEqual(self.config.get("escaped"), str('''"a "b" 'c' d"''')) self.assertEqual(self.config.get("escaped-quoted"), str('''"a "b" 'c' d"''')) def test_strings_literals_clash(self): # we want to pass literal string 'true' (and not have it converted to bool(True)) self.obj.apply_overrides(['yes="true"', 'list="[1,2,3]"'], self.config) self.assertEqual(self.config.get("yes"), str("true")) self.assertEqual(self.config.get("list"), str("[1,2,3]")) def test_null(self): self.obj.apply_overrides(['nothing=null'], self.config) self.assertEqual(self.config.get("nothing"), None) def test_objects(self): self.config.merge({ "obj": { "key": "142857", }, }) self.obj.apply_overrides(['obj={"key": "value"}'], self.config) self.assertEqual(self.config.get("obj").get("key"), str("value")) def test_lists(self): self.config.merge({ "list": ["stuff"], }) self.obj.apply_overrides(['list=[1, 2.0, "str", []]'], self.config) self.assertEqual(self.config.get("list"), list([1, 2.0, "str", []])) def test_nested_quotation(self): # bzt -o man='{"name": "Robert \"Destroyer of Worlds\" Oppenheimer"}' self.obj.apply_overrides(['''man={"name": "Robert \\"Destroyer of Worlds\\" Oppenheimer"}'''], self.config) self.assertEqual(self.config.get("man").get("name"), str('Robert "Destroyer of Worlds" Oppenheimer')) def test_no_override(self): self.obj.apply_overrides(['nothing='], self.config) self.assertEqual(self.config.get("nothing"), None) def test_unquoted_keys(self): self.obj.apply_overrides(['obj={abc: def}'], self.config) self.assertEqual(self.config.get("obj").get("abc"), str("def")) def test_override_delete_from_list(self): self.config["items"] = [1, 2, 3] self.config["dict"] = {"1": 1, "2": 2, "3": 3} self.obj.apply_overrides(['items.^-4=null'], self.config) self.obj.apply_overrides(['items.^1=null'], self.config) self.obj.apply_overrides(['dict.^2=null'], self.config) self.assertEqual(self.config.get("items"), [1, 3]) self.assertEqual(self.config.get("dict"), {"1": 1, "3": 3})
def __get_url_shorthands(self, configs): """ :type configs: list :return: list """ urls = [] for candidate in configs[:]: if is_url(candidate): urls.append(candidate) configs.remove(candidate) if urls: self.log.debug("Adding HTTP shorthand config for: %s", urls) config_fds = NamedTemporaryFile(prefix="http_", suffix=".yml") fname = config_fds.name config_fds.close() config = Configuration.from_dict({ "execution": [{ "concurrency": "${__tstFeedback(Throughput_Limiter,1,${__P(concurrencyCap,1)},2)}", "hold-for": "2m", "throughput": "${__P(throughput,600)}", "scenario": "linear-growth", }], "scenarios": { "linear-growth": { "retrieve-resources": False, "timeout": "5s", "keepalive": False, "requests": [{ "action": "pause", "pause-duration": 0, "jsr223": [{ "language": "javascript", "execute": "before", "script-text": """ var startTime = parseInt(props.get("startTime")); if (!startTime) { startTime = Math.floor((new Date()).getTime() / 1000); props.put("startTime", startTime); } else { var now = Math.floor((new Date()).getTime() / 1000); var offset = now - startTime; if (offset < 60) { var targetOffset = Math.max(offset * 10, 10); props.put("throughput", targetOffset.toString()); } }""" }] }] + urls, } }, "modules": { "jmeter": { "properties": { "throughput": 1, "concurrencyCap": 500, }, } } }) config.dump(fname, Configuration.JSON) return [fname] else: return []
def setUp(self): super(TestConfigOverrider, self).setUp() self.obj = ConfigOverrider(logging.getLogger()) self.config = Configuration()
class TestConfigOverrider(BZTestCase): def setUp(self): super(TestConfigOverrider, self).setUp() self.obj = ConfigOverrider(logging.getLogger()) self.config = Configuration() def test_numbers(self): self.obj.apply_overrides(["int=11", "float=3.14"], self.config) self.assertEqual(self.config.get("int"), int(11)) self.assertEqual(self.config.get("float"), float(3.14)) def test_booleans(self): self.obj.apply_overrides(["yes=true", "no=false"], self.config) self.assertEqual(self.config.get("yes"), bool(True)) self.assertEqual(self.config.get("no"), bool(False)) def test_strings(self): self.obj.apply_overrides([ "plain=ima plain string", """quoted='"ima quoted string"'""", """empty-quoted='""'""", '''escaped="a "b" 'c' d"''', '''escaped-quoted="a "b" 'c' d"''' ], self.config) self.assertEqual(self.config.get("plain"), str("ima plain string")) self.assertEqual(self.config.get("quoted"), str('''"ima quoted string"''')) self.assertEqual(self.config.get("empty-quoted"), str('""')) self.assertEqual(self.config.get("escaped"), str('''"a "b" 'c' d"''')) self.assertEqual(self.config.get("escaped-quoted"), str('''"a "b" 'c' d"''')) def test_strings_literals_clash(self): # we want to pass literal string 'true' (and not have it converted to bool(True)) self.obj.apply_overrides(['yes="true"', 'list="[1,2,3]"'], self.config) self.assertEqual(self.config.get("yes"), str("true")) self.assertEqual(self.config.get("list"), str("[1,2,3]")) def test_null(self): self.obj.apply_overrides(['nothing=null'], self.config) self.assertEqual(self.config.get("nothing"), None) def test_objects(self): self.config.merge({ "obj": { "key": "142857", }, }) self.obj.apply_overrides(['obj={"key": "value"}'], self.config) self.assertEqual(self.config.get("obj").get("key"), str("value")) def test_lists(self): self.config.merge({ "list": ["stuff"], }) self.obj.apply_overrides(['list=[1, 2.0, "str", []]'], self.config) self.assertEqual(self.config.get("list"), list([1, 2.0, "str", []])) def test_nested_quotation(self): # bzt -o man='{"name": "Robert \"Destroyer of Worlds\" Oppenheimer"}' self.obj.apply_overrides([ '''man={"name": "Robert \\"Destroyer of Worlds\\" Oppenheimer"}''' ], self.config) self.assertEqual( self.config.get("man").get("name"), str('Robert "Destroyer of Worlds" Oppenheimer')) def test_no_override(self): self.obj.apply_overrides(['nothing='], self.config) self.assertEqual(self.config.get("nothing"), None) def test_unquoted_keys(self): self.obj.apply_overrides(['obj={abc: def}'], self.config) self.assertEqual(self.config.get("obj").get("abc"), str("def")) def test_override_delete_from_list(self): self.config["items"] = [1, 2, 3] self.config["dict"] = {"1": 1, "2": 2, "3": 3} self.obj.apply_overrides(['items.^-4=null'], self.config) self.obj.apply_overrides(['items.^1=null'], self.config) self.obj.apply_overrides(['dict.^2=null'], self.config) self.assertEqual(self.config.get("items"), [1, 3]) self.assertEqual(self.config.get("dict"), {"1": 1, "3": 3}) def test_override_multiple(self): self.config["items"] = [1, 2, 3] self.config["dict"] = { "listObj": [{ "k1": "v1" }, { "k2": "v2" }, { "k3": "v3" }], "lislis": [1, 2, 3, 4], "k1": "v3" } self.obj.apply_overrides(['items.*1=v2'], self.config) self.obj.apply_overrides(['dict.*k1=v2'], self.config) self.assertEqual( self.config.get("dict"), { 'listObj': [{ 'k1': 'v2' }, { 'k2': 'v2' }, { 'k3': 'v3' }], 'lislis': [1, 2, 3, 4], 'k1': 'v2' }) self.assertEqual(self.config.get("items"), [1, 2, 3])