def test_general(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/general.yaml")) self.assertEqual(len(semconv.models), 2) expected = { "id": "network", "prefix": "net", "extends": "", "n_constraints": 0, "attributes": [ "net.transport", "net.peer.ip", "net.peer.port", "net.peer.name", "net.host.ip", "net.host.port", "net.host.name", ], } self.semantic_convention_check( list(semconv.models.values())[0], expected) expected = { "id": "identity", "prefix": "enduser", "extends": "", "n_constraints": 0, "attributes": ["enduser.id", "enduser.role", "enduser.scope"], } self.semantic_convention_check( list(semconv.models.values())[1], expected)
def test_wrong_duplicate(self): semconv = SemanticConventionSet(debug=False) semconv.parse( self.load_file("markdown/parameter_wrong_duplicate/http.yaml")) semconv.parse( self.load_file("markdown/parameter_wrong_duplicate/faas.yaml")) semconv.parse( self.load_file("markdown/parameter_wrong_duplicate/general.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 7) with open( self.load_file("markdown/parameter_wrong_duplicate/input.md"), "r") as markdown: content = markdown.read() expected = "" with self.assertRaises(ValueError) as ex: self.check_render( semconv, "markdown/parameter_wrong_duplicate/", "markdown/parameter_wrong_duplicate/input.md", content, expected, ) self.fail() e = ex.exception msg = e.args[0] self.assertIn("Parameter", msg) self.assertIn("already defined", msg)
def test_rpc(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/rpc.yaml")) self.assertEqual(len(semconv.models), 3) expected = { "id": "rpc", "prefix": "rpc", "extends": "", "n_constraints": 1, "attributes": ["rpc.service"], } self.semantic_convention_check( list(semconv.models.values())[0], expected) expected = { "id": "grpc.client", "prefix": "", "extends": "rpc", "n_constraints": 0, "attributes": ["net.peer.port"], } self.semantic_convention_check( list(semconv.models.values())[1], expected) expected = { "id": "grpc.server", "prefix": "", "extends": "rpc", "n_constraints": 0, "attributes": ["net.peer.port"], } self.semantic_convention_check( list(semconv.models.values())[2], expected)
def test_faas(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/faas.yaml")) self.assertEqual(len(semconv.models), 5) expected = { "id": "faas", "prefix": "faas", "extends": "", "n_constraints": 0, "attributes": ["faas.trigger", "faas.execution"], } self.semantic_convention_check( list(semconv.models.values())[0], expected) expected = { "id": "faas.datasource", "prefix": "faas.document", "extends": "faas", "n_constraints": 0, "attributes": [ "faas.document.collection", "faas.document.operation", "faas.document.time", "faas.document.name", ], } self.semantic_convention_check( list(semconv.models.values())[1], expected) expected = { "id": "faas.http", "prefix": "", "extends": "faas", "n_constraints": 1, "attributes": [], } self.semantic_convention_check( list(semconv.models.values())[2], expected) expected = { "id": "faas.pubsub", "prefix": "", "extends": "faas", "n_constraints": 0, "attributes": [], } self.semantic_convention_check( list(semconv.models.values())[3], expected) expected = { "id": "faas.timer", "prefix": "faas", "extends": "faas", "n_constraints": 0, "attributes": ["faas.time", "faas.cron"], } self.semantic_convention_check( list(semconv.models.values())[4], expected)
def test_include(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/http.yaml")) semconv.parse(self.load_file("yaml/faas.yaml")) semconv.parse(self.load_file("yaml/general.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 10) faas_http = [s for s in semconv.models.values() if s.semconv_id == "faas.http"][ 0 ] expected = { "id": "faas.http", "prefix": "faas", "extends": "faas", "n_constraints": 2, "attributes": [ # Parent "faas.trigger", "faas.execution", # Include "http.method", "http.url", "http.target", "http.host", "http.scheme", "http.status_code", "http.status_text", "http.flavor", "http.user_agent", "http.server_name", ], } self.semantic_convention_check(faas_http, expected)
def test_parameter_remove_constraint(self): semconv = SemanticConventionSet(debug=False) semconv.parse( self.load_file( "markdown/parameter_remove_constraint/database.yaml")) semconv.parse( self.load_file( "markdown/parameter_remove_constraint/general.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 6) with open( self.load_file( "markdown/parameter_remove_constraint/input.md"), "r") as markdown: content = markdown.read() with open( self.load_file( "markdown/parameter_remove_constraint/expected.md"), "r") as markdown: expected = markdown.read() self.check_render( semconv, "markdown/parameter_remove_constraint/", "markdown/parameter_remove_constraint/input.md", content, expected, )
def test_populate_other_attributes(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/http.yaml")) semconv.parse(self.load_file("yaml/faas.yaml")) semconv.parse(self.load_file("yaml/general.yaml")) semconv.finish() models = sorted(semconv.models.values(), key=lambda m: m.semconv_id) self.assertEqual(len(models), 10) self.assertEqual(len(models[0].constraints), 0) self.assertEqual(len(models[1].constraints), 0) self.assertEqual(len(models[2].constraints), 2) self.assertTrue(isinstance(models[2].constraints[0], Include)) self.assertEqual(len(models[2].constraints[1].choice_list_attributes), 4) self.assertEqual(len(models[3].constraints), 0) self.assertEqual(len(models[4].constraints), 0) self.assertEqual(len(models[5].constraints), 0) self.assertEqual(len(models[6].constraints), 1) self.assertEqual(len(models[6].constraints[0].choice_list_attributes), 4) self.assertEqual(len(models[7].constraints), 1) self.assertEqual(len(models[6].constraints[0].choice_list_attributes), 4) self.assertEqual(len(models[8].constraints), 0) self.assertEqual(len(models[9].constraints), 0)
def test_id_clash(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/errors/id_clash/span_faas.yaml")) semconv.parse( self.load_file("yaml/errors/id_clash/resource_faas.yaml")) semconv.finish() self.assertTrue(semconv.errors)
def test_http(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/http.yaml")) self.assertEqual(len(semconv.models), 3) expected = { "id": "http", "prefix": "http", "extends": "", "n_constraints": 0, "attributes": [ "http.method", "http.url", "http.target", "http.host", "http.scheme", "http.status_code", "http.status_text", "http.flavor", "http.user_agent", ], } self.semantic_convention_check( list(semconv.models.values())[0], expected) expected = { "id": "http.client", "prefix": "http", "extends": "http", "n_constraints": 1, "attributes": [], } self.semantic_convention_check( list(semconv.models.values())[1], expected) expected = { "id": "http.server", "prefix": "http", "extends": "http", "n_constraints": 1, "attributes": ["http.server_name"], } self.semantic_convention_check( list(semconv.models.values())[2], expected)
def test_resource(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/cloud.yaml")) self.assertEqual(len(semconv.models), 1) cloud = list(semconv.models.values())[0] expected = { "id": "cloud", "prefix": "cloud", "extends": "", "n_constraints": 0, "attributes": [ "cloud.provider", "cloud.account.id", "cloud.region", "cloud.zone", ], } self.semantic_convention_check(cloud, expected)
def test_extends_prefix(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/extends/http.yaml")) semconv.parse(self.load_file("yaml/extends/child.http.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 3) base = list(semconv.models.values())[1] child = list(semconv.models.values())[2] self.assertEqual(base.prefix, "http") self.assertEqual(child.prefix, "child.http")
def test_database(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/database.yaml")) self.assertEqual(len(semconv.models), 1) expected = { "id": "database", "prefix": "db", "extends": "", "n_constraints": 1, "attributes": [ "db.type", "db.instance", "db.statement", "db.url", "db.user", ], } self.semantic_convention_check(list(semconv.models.values())[0], expected)
def get_data_single_file(self, semconvset: SemanticConventionSet, template_path: str) -> dict: """Returns a dictionary that contains all SemanticConventions to fill the template.""" data = { "template": template_path, "semconvs": semconvset.models, "attributes": semconvset.attributes(), } data.update(self.parameters) return data
def testEmpty(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("markdown/empty/http.yaml")) semconv.parse(self.load_file("markdown/empty/general.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 5) with open(self.load_file("markdown/empty/input.md"), "r") as markdown: content = markdown.read() with open(self.load_file("markdown/empty/expected.md"), "r") as markdown: expected = markdown.read() self.check_render(semconv, "markdown/empty/", "markdown/empty/input.md", content, expected)
def test_event(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/event.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 1) event = list(semconv.models.values())[0] expected = { "id": "exception", "prefix": "exception", "extends": "", "n_constraints": 1, "attributes": [ "exception.type", "exception.message", "exception.stacktrace", "exception.escaped", ], } self.semantic_convention_check(event, expected) constraint = event.constraints[0] self.assertIsInstance(constraint, AnyOf) constraint: AnyOf for choice_index, attr_list in enumerate(constraint.choice_list_ids): for attr_index, attr in enumerate(attr_list): self.assertEqual( event.attrs_by_name.get(attr), constraint.choice_list_attributes[choice_index] [attr_index], )
def test_ref(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/rpc.yaml")) semconv.parse(self.load_file("yaml/general.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 5) client = list(semconv.models.values())[1] server = list(semconv.models.values())[2] self.assertIsNotNone(client.attributes[1].ref) self.assertIsNotNone(client.attributes[1].attr_type) self.assertIsNotNone(server.attributes[1].ref) self.assertIsNotNone(server.attributes[1].attr_type)
def parse_semconv(args, parser) -> SemanticConventionSet: semconv = SemanticConventionSet(args.debug) find_yaml(args) for file in sorted(args.files): if not file.endswith(".yaml") and not file.endswith(".yml"): parser.error("{} is not a yaml file.".format(file)) semconv.parse(file) semconv.finish() if semconv.has_error(): sys.exit(1) return semconv
def test_markdown_link(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/links.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 1) s = list(semconv.models.values())[0] for attr in s.attributes: brief = attr.brief self.assertEqual(brief.raw_text, brief.__str__())
def test_error_missing_end(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("markdown/missing_end_tag/http.yaml")) semconv.parse(self.load_file("markdown/missing_end_tag/general.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 5) with open(self.load_file("markdown/missing_end_tag/input.md"), "r") as markdown: content = markdown.read() with self.assertRaises(Exception) as ex: renderer = MarkdownRenderer( self.load_file("markdown/missing_end_tag/"), semconv) renderer._render_single_file(content, "markdown/missing_end_tag/input.md", io.StringIO()) self.assertEqual("Missing ending <!-- endsemconv --> tag", ex.exception.args[0])
def test_error_wrong_id(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("markdown/wrong_semconv_id/http.yaml")) semconv.parse(self.load_file("markdown/wrong_semconv_id/general.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 5) with open(self.load_file("markdown/wrong_semconv_id/input.md"), "r") as markdown: content = markdown.read() with self.assertRaises(Exception) as ex: renderer = MarkdownRenderer( self.load_file("markdown/wrong_semconv_id/"), semconv) renderer._render_single_file(content, "markdown/wrong_semconv_id/input.md", io.StringIO()) self.assertEqual("Semantic Convention ID db not found", ex.exception.args[0])
def testRef(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("markdown/ref/general.yaml")) semconv.parse(self.load_file("markdown/ref/rpc.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 5) md = self.load_file("markdown/ref/input/input_rpc.md") with open(md, "r") as markdown: content = markdown.read() renderer = MarkdownRenderer(self.load_file("markdown/ref/input"), semconv) output = io.StringIO() renderer._render_single_file(content, md, output) with open(self.load_file("markdown/ref/expected.md"), "r") as markdown: expected = markdown.read() assert output.getvalue() == expected
def test_validate_anyof_attributes(self): with self.assertRaises(ValidationError) as ex: semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/errors/validate_anyof.yaml")) semconv.finish() e = ex.exception msg = e.message.lower() self.assertIn("any_of attribute", msg) self.assertIn("does not exists", msg) self.assertEqual(e.line, 15)
def test_missing_event(self): with self.assertRaises(ValidationError) as ex: semconv = SemanticConventionSet(debug=False) semconv.parse( self.load_file("yaml/errors/events/missing_event.yaml")) semconv.finish() e = ex.exception msg = e.message.lower() self.assertIn("as event but the latter cannot be found!", msg) self.assertEqual(e.line, 2)
def test_span_with_event(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/event.yaml")) semconv.parse(self.load_file("yaml/span_event.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 3) semconvs = list(semconv.models.values()) self.assertTrue(isinstance(semconvs[0], EventSemanticConvention)) self.assertTrue(isinstance(semconvs[1], SpanSemanticConvention)) self.assertTrue(isinstance(semconvs[2], EventSemanticConvention)) event_semconv = semconvs[1] self.assertEqual(2, len(event_semconv.events)) self.assertTrue( isinstance(event_semconv.events[0], EventSemanticConvention)) self.assertTrue( isinstance(event_semconv.events[1], EventSemanticConvention)) self.assertEqual("exception", event_semconv.events[0].semconv_id) self.assertEqual("random.event", event_semconv.events[1].semconv_id)
def test_units(self): semconv = SemanticConventionSet(debug=True) semconv.parse(self.load_file("yaml/metrics/units.yaml")) semconv.finish() assert len(semconv.models) == 1 content = self.read_file("markdown/metrics/units_input.md") expected = self.read_file("markdown/metrics/units_output.md") self.check_render(semconv, "markdown/metrics/", "markdown/metrics/units_input.md", content, expected)
def test_deprecation(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("yaml/deprecated/http.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 1) self.assertIsNotNone(list(semconv.models.values())[0].attributes[0].deprecated) self.assertEqual( list(semconv.models.values())[0].attributes[0].deprecated, "Use attribute `nonDepecrated`.", ) self.assertIsNone(list(semconv.models.values())[0].attributes[3].deprecated)
def check( self, input_dir: str, options=MarkdownOptions(), *, expected_name="expected.md", extra_yaml_dirs: Sequence[str] = (), assert_raises=None ) -> Optional[BaseException]: dirpath = Path(self.get_file_path(input_dir)) if not dirpath.is_dir(): raise ValueError( "Input dir does not exist (or is not a dir): " + str(dirpath) ) semconv = SemanticConventionSet(debug=True) for fname in dirpath.glob("*.yaml"): print("Parsing", fname) semconv.parse(fname) for extra_dir in extra_yaml_dirs: for fname in Path(self.get_file_path(extra_dir)).glob("*.yaml"): print("Parsing", fname) semconv.parse(fname) semconv.finish() inputpath = dirpath / "input.md" output = io.StringIO() def do_render(): renderer = MarkdownRenderer(str(dirpath), semconv, options) renderer._render_single_file( inputpath.read_text(encoding="utf-8"), str(inputpath), output ) if assert_raises: with self.assertRaises(assert_raises) as ex: do_render() return ex.exception do_render() result = output.getvalue() assert result == (dirpath / expected_name).read_text(encoding="utf-8") return None
def test_wrong_event_type(self): with self.assertRaises(ValidationError) as ex: semconv = SemanticConventionSet(debug=False) semconv.parse( self.load_file("yaml/errors/events/no_event_type.yaml")) semconv.finish() e = ex.exception msg = e.message.lower() self.assertIn( "as event but the latter is not a semantic convention for events", msg) self.assertEqual(e.line, 2)
def test_parameter_full(self): semconv = SemanticConventionSet(debug=False) semconv.parse(self.load_file("markdown/parameter_full/http.yaml")) semconv.parse(self.load_file("markdown/parameter_full/faas.yaml")) semconv.parse(self.load_file("markdown/parameter_full/general.yaml")) semconv.finish() self.assertEqual(len(semconv.models), 7) with open(self.load_file("markdown/parameter_full/input.md"), "r") as markdown: content = markdown.read() with open(self.load_file("markdown/parameter_full/expected.md"), "r") as markdown: expected = markdown.read() self.check_render( semconv, "markdown/parameter_full/", "markdown/parameter_full/input.md", content, expected, )
def test_codegen_units(test_file_path, read_test_file): semconv = SemanticConventionSet(debug=False) semconv.parse(test_file_path("yaml", "metrics", "units.yaml")) semconv.finish() template_path = test_file_path("jinja", "metrics", "units_template") renderer = CodeRenderer({}) output = io.StringIO() renderer.render(semconv, template_path, output, None) result = output.getvalue() expected = read_test_file("jinja", "metrics", "expected.java") assert result == expected