tests: Add C versions of gen-ust-events-constructor
[lttng-tools.git] / tests / regression / ust / ust-constructor / test_ust_constructor.py
index d7818186c08f9815a2cc79f59e697583e6c052d7..130d0657da35a988148142d8a7071601629b26aa 100755 (executable)
@@ -5,9 +5,11 @@
 #
 # SPDX-License-Identifier: GPL-2.0-only
 
+import copy
 import pathlib
 import sys
 import os
+import subprocess
 from typing import Any, Callable, Type
 
 """
@@ -25,83 +27,68 @@ sys.path.append(str(test_utils_import_path))
 import lttngtest
 import bt2
 
-expected_events = [
-    {"name": "tp_so:constructor_c_provider_shared_library", "msg": None, "count": 0},
-    {"name": "tp_a:constructor_c_provider_static_archive", "msg": None, "count": 0},
-    {
-        "name": "tp_so:constructor_cplusplus_provider_shared_library",
-        "msg": "global - shared library define and provider",
-        "count": 0,
-    },
-    {
-        "name": "tp_a:constructor_cplusplus_provider_static_archive",
-        "msg": "global - static archive define and provider",
-        "count": 0,
-    },
-    {"name": "tp:constructor_c_across_units_before_define", "msg": None, "count": 0},
+# Determine if LTTNG_UST_ALLOCATE_COMPOUND_LITERAL_ON_HEAP is set. This will
+# affect if certain events may or may not be expected when compiling with
+# C++.
+# @see https://github.com/lttng/lttng-ust/blob/47fa3e4ed7ab43e034dc61fc1480f919f4ee51d0/include/lttng/ust-compiler.h#L51
+#
+compound_literal_on_heap = False
+process = subprocess.Popen(
+    [
+        os.path.join(
+            str(test_utils_import_path),
+            "testapp",
+            "gen-ust-events-constructor",
+            "uses_heap",
+        )
+    ]
+)
+process.wait()
+if process.returncode == 0:
+    compound_literal_on_heap = True
+
+expected_events_common_cpp = [
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - across units before define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
-    {"name": "tp:constructor_c_same_unit_before_define", "msg": None, "count": 0},
-    {"name": "tp:constructor_c_same_unit_after_define", "msg": None, "count": 0},
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - same unit before define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - same unit after define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
-    {"name": "tp:constructor_c_across_units_after_define", "msg": None, "count": 0},
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - across units after define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
-    {"name": "tp:constructor_c_same_unit_before_provider", "msg": None, "count": 0},
-    {"name": "tp:constructor_c_same_unit_after_provider", "msg": None, "count": 0},
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - same unit before provider",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - same unit after provider",
         "count": 0,
     },
-    {"name": "tp:constructor_c_across_units_after_provider", "msg": None, "count": 0},
     {
         "name": "tp:constructor_cplusplus",
         "msg": "global - across units after provider",
         "count": 0,
     },
     {"name": "tp:constructor_cplusplus", "msg": "main() local", "count": 0},
-    {
-        "name": "tp_so:constructor_cplusplus_provider_shared_library",
-        "msg": "main() local - shared library define and provider",
-        "count": 0,
-    },
-    {
-        "name": "tp_a:constructor_cplusplus_provider_static_archive",
-        "msg": "main() local - static archive define and provider",
-        "count": 0,
-    },
-    {"name": "tp:main", "msg": None, "count": 0},
-    {
-        "name": "tp_a:destructor_cplusplus_provider_static_archive",
-        "msg": "main() local - static archive define and provider",
-        "count": 0,
-    },
-    {
-        "name": "tp_so:destructor_cplusplus_provider_shared_library",
-        "msg": "main() local - shared library define and provider",
-        "count": 0,
-    },
     {"name": "tp:destructor_cplusplus", "msg": "main() local", "count": 0},
     {
         "name": "tp:destructor_cplusplus",
@@ -117,30 +104,131 @@ expected_events = [
         "name": "tp:destructor_cplusplus",
         "msg": "global - same unit before provider",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:destructor_cplusplus",
         "msg": "global - across units after define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:destructor_cplusplus",
         "msg": "global - same unit after define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:destructor_cplusplus",
         "msg": "global - same unit before define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
     {
         "name": "tp:destructor_cplusplus",
         "msg": "global - across units before define",
         "count": 0,
+        "may_fail": compound_literal_on_heap,
     },
+]
+
+expected_events_common = [
     {
-        "name": "tp_a:destructor_cplusplus_provider_static_archive",
-        "msg": "global - static archive define and provider",
+        "name": "tp:constructor_c_across_units_before_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_same_unit_before_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_same_unit_after_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_across_units_after_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_same_unit_before_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:constructor_c_same_unit_after_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {"name": "tp:constructor_c_across_units_after_provider", "msg": None, "count": 0},
+    {"name": "tp:main", "msg": None, "count": 0},
+    {
+        "name": "tp:destructor_c_across_units_after_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_same_unit_after_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_same_unit_before_provider",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_across_units_after_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_same_unit_after_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_same_unit_before_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp:destructor_c_across_units_before_define",
+        "msg": None,
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+]
+
+expected_events_tp_so_cpp = [
+    {
+        "name": "tp_so:constructor_cplusplus_provider_shared_library",
+        "msg": "global - shared library define and provider",
+        "count": 0,
+    },
+    {
+        "name": "tp_so:constructor_cplusplus_provider_shared_library",
+        "msg": "main() local - shared library define and provider",
+        "count": 0,
+    },
+    {
+        "name": "tp_so:destructor_cplusplus_provider_shared_library",
+        "msg": "main() local - shared library define and provider",
         "count": 0,
     },
     {
@@ -148,25 +236,47 @@ expected_events = [
         "msg": "global - shared library define and provider",
         "count": 0,
     },
-    {"name": "tp:destructor_c_across_units_after_provider", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_same_unit_after_provider", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_same_unit_before_provider", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_across_units_after_define", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_same_unit_after_define", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_same_unit_before_define", "msg": None, "count": 0},
-    {"name": "tp:destructor_c_across_units_before_define", "msg": None, "count": 0},
-    {"name": "tp_a:destructor_c_provider_static_archive", "msg": None, "count": 0},
-    {"name": "tp_so:destructor_c_provider_shared_library", "msg": None, "count": 0},
 ]
 
-num_tests = 7 + len(expected_events)
+expected_events_tp_so = [
+    {"name": "tp_so_c:constructor_c_provider_shared_library", "msg": None, "count": 0},
+    {"name": "tp_so_c:destructor_c_provider_shared_library", "msg": None, "count": 0},
+]
+
+expected_events_tp_a_cpp = [
+    {
+        "name": "tp_a:constructor_cplusplus_provider_static_archive",
+        "msg": "global - static archive define and provider",
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+    {
+        "name": "tp_a:constructor_cplusplus_provider_static_archive",
+        "msg": "main() local - static archive define and provider",
+        "count": 0,
+    },
+    {
+        "name": "tp_a:destructor_cplusplus_provider_static_archive",
+        "msg": "main() local - static archive define and provider",
+        "count": 0,
+    },
+    {
+        "name": "tp_a:destructor_cplusplus_provider_static_archive",
+        "msg": "global - static archive define and provider",
+        "count": 0,
+        "may_fail": compound_literal_on_heap,
+    },
+]
+
+expected_events_tp_a = [
+    {"name": "tp_a_c:constructor_c_provider_static_archive", "msg": None, "count": 0},
+    {"name": "tp_a_c:destructor_c_provider_static_archive", "msg": None, "count": 0},
+]
 
 
-def capture_trace(tap, test_env):
+def capture_trace(tap, test_env, application, description):
     # type: (lttngtest.TapGenerator, lttngtest._Environment) -> lttngtest.LocalSessionOutputLocation
-    tap.diagnostic(
-        "Capture trace from application with instrumented C/C++ constructors/destructors"
-    )
+    tap.diagnostic(description)
 
     session_output_location = lttngtest.LocalSessionOutputLocation(
         test_env.create_temporary_directory("trace")
@@ -192,8 +302,10 @@ def capture_trace(tap, test_env):
     ) as test_case:
         session.start()
 
-    test_app = test_env.launch_trace_test_constructor_application()
-    with tap.case("Run test app".format(session_name=session.name)) as test_case:
+    test_app = test_env.launch_test_application(application)
+    with tap.case(
+        "Run test app '{}'".format(application, session_name=session.name)
+    ) as test_case:
         test_app.wait_for_exit()
 
     with tap.case(
@@ -209,7 +321,7 @@ def capture_trace(tap, test_env):
     return session_output_location
 
 
-def validate_trace(trace_location, tap):
+def validate_trace(trace_location, tap, expected_events):
     # type: (pathlib.Path, lttngtest.TapGenerator)
     unknown_event_count = 0
 
@@ -244,21 +356,83 @@ def validate_trace(trace_location, tap):
             )
 
     for event in expected_events:
-        tap.test(
-            event["count"] == 1,
-            'Found expected event name="{}" msg="{}"'.format(
-                event["name"], str(event["msg"])
+        may_fail = "may_fail" in event.keys() and event["may_fail"]
+        if not may_fail:
+            tap.test(
+                event["count"] == 1,
+                'Found expected event name="{}" msg="{}"'.format(
+                    event["name"], str(event["msg"])
+                ),
             ),
-        )
+        else:
+            tap.skip("Event '{}' may or may not be recorded".format(event["name"]))
 
     tap.test(unknown_event_count == 0, "Found no unexpected events")
 
 
-tap = lttngtest.TapGenerator(num_tests)
-tap.diagnostic("Test user space constructor/destructor instrumentation coverage")
+success = True
+tests = [
+    {
+        "description": "Test user space constructor/destructor instrumentation coverage (C++ w/ static archive)",
+        "application": "gen-ust-events-constructor/gen-ust-events-constructor-a",
+        "expected_events": copy.deepcopy(
+            expected_events_common
+            + expected_events_common_cpp
+            + expected_events_tp_a
+            + expected_events_tp_a_cpp
+        ),
+        "skip_if_application_not_present": False,
+    },
+    {
+        "description": "Test user space constructor/destructor instrumentation coverage (C++ w/ dynamic object",
+        "application": "gen-ust-events-constructor/gen-ust-events-constructor-so",
+        "expected_events": copy.deepcopy(
+            expected_events_common
+            + expected_events_common_cpp
+            + expected_events_tp_so
+            + expected_events_tp_so_cpp
+        ),
+        # This application is not be built when `NO_SHARED` is set in the
+        # configuration options.
+        "skip_if_application_not_present": True,
+    },
+    {
+        "description": "Test user space constructor/destructor instrumentation coverage (C w/ static archive)",
+        "application": "gen-ust-events-constructor/gen-ust-events-c-constructor-a",
+        "expected_events": copy.deepcopy(expected_events_common + expected_events_tp_a),
+        "skip_if_application_not_present": False,
+    },
+    {
+        "description": "Test user space constructor/destructor instrumentation coverage (C w/ dynamic object",
+        "application": "gen-ust-events-constructor/gen-ust-events-c-constructor-so",
+        "expected_events": copy.deepcopy(
+            expected_events_common + expected_events_tp_so
+        ),
+        # This application is not be built when `NO_SHARED` is set in the
+        # configuration options.
+        "skip_if_application_not_present": True,
+    },
+]
+
+success = True
+for test in tests:
+    tap = lttngtest.TapGenerator(7 + len(test["expected_events"]))
+    with lttngtest.test_environment(with_sessiond=True, log=tap.diagnostic) as test_env:
+        try:
+            outputlocation = capture_trace(
+                tap, test_env, test["application"], test["description"]
+            )
+        except FileNotFoundError as fne:
+            tap.diagnostic(fne)
+            if test["skip_if_application_not_present"]:
+                tap.skip(
+                    "Test application '{}' not found".format(test["application"]),
+                    tap.remaining_test_cases,
+                )
+            break
+        # Warning: validate_trace mutates test['expected_events']
+        validate_trace(outputlocation.path, tap, test["expected_events"])
+    success = success and tap.is_successful
 
-with lttngtest.test_environment(with_sessiond=True, log=tap.diagnostic) as test_env:
-    outputlocation = capture_trace(tap, test_env)
-    validate_trace(outputlocation.path, tap)
 
-sys.exit(0 if tap.is_successful else 1)
+sys.exit(0 if success else 1)
This page took 0.026586 seconds and 4 git commands to generate.