Introduce save load test
[deliverable/lttng-ivc.git] / lttng_ivc / tests / tools_save-load / test_save_load.py
diff --git a/lttng_ivc/tests/tools_save-load/test_save_load.py b/lttng_ivc/tests/tools_save-load/test_save_load.py
new file mode 100644 (file)
index 0000000..a513934
--- /dev/null
@@ -0,0 +1,287 @@
+import pytest
+import os
+import shutil
+import subprocess
+
+import lttng_ivc.utils.ProjectFactory as ProjectFactory
+import lttng_ivc.utils.utils as utils
+import lttng_ivc.utils.runtime as Run
+import lttng_ivc.settings as Settings
+
+from lttng_ivc.utils.utils import xpath_query
+
+"""
+"""
+
+
+test_matrix_app_contexts = [
+    ("lttng-tools-2.8", "lttng-tools-2.7",   False),
+    ("lttng-tools-2.9", "lttng-tools-2.8",   True),
+    ("lttng-tools-2.8", "lttng-tools-2.9",   True),
+    pytest.param("lttng-tools-2.8", "lttng-tools-2.10",  True, marks=pytest.mark.xfail(reason="See https://bugs.lttng.org/issues/1136")),
+]
+
+test_matrix_blocking_timeout = [
+        ("lttng-tools-2.10", "lttng-tools-2.7",   False),
+        ("lttng-tools-2.10", "lttng-tools-2.8",   False),
+        ("lttng-tools-2.10", "lttng-tools-2.9",   False),
+        ("lttng-tools-2.10", "lttng-tools-2.10",  True),
+]
+
+test_matrix_monitor_timer_interval = [
+        ("lttng-tools-2.10", "lttng-tools-2.7",   False),
+        ("lttng-tools-2.10", "lttng-tools-2.8",   False),
+        ("lttng-tools-2.10", "lttng-tools-2.9",   False),
+        ("lttng-tools-2.10", "lttng-tools-2.10",  True),
+]
+
+runtime_matrix_app_contexts = []
+runtime_matrix_blocking_timeout = []
+runtime_matrix_monitor_timer_interval = []
+
+
+if not Settings.test_only:
+    runtime_matrix_app_contexts = test_matrix_app_contexts
+    runtime_matrix_blocking_timeout = test_matrix_blocking_timeout
+    runtime_matrix_monitor_timer_interval = test_matrix_monitor_timer_interval
+else:
+    for tup in test_matrix_app_contexts:
+        if(tup[0] in Settings.test_only or tup[1] in Settings.test_only):
+            runtime_matrix_app_contexts.append(tup)
+    for tup in test_matrix_blocking_timeout:
+        if(tup[0] in Settings.test_only or tup[1] in Settings.test_only):
+            runtime_matrix_blocking_timeout.append(tup)
+    for tup in test_matrix_monitor_timer_interval:
+        if(tup[0] in Settings.test_only or tup[1] in Settings.test_only):
+            runtime_matrix_monitor_timer_interval.append(tup)
+
+
+def validate_app_context(session_name, save_file):
+    xpath_provider_name = '/sessions/session[name="{}"]/domains/domain[type="JUL" or type="LOG4J"]/channels/channel/contexts/context/app/provider_name'.format(session_name)
+    xpath_ctx_name = '/sessions/session[name="{}"]/domains/domain[type="JUL" or type="LOG4J"]/channels/channel/contexts/context/app/ctx_name'.format(session_name)
+    xpath_node_expected = 2
+
+    # Check that the file is present
+    assert(os.path.isfile(save_file))
+    # Validate provider name
+    node_list = xpath_query(save_file, xpath_provider_name)
+    assert(len(node_list) == xpath_node_expected)
+    for node in node_list:
+        assert(node.text == "myRetriever")
+
+    # Validate ctx_name
+    node_list = xpath_query(save_file, xpath_ctx_name)
+    assert(len(node_list) == xpath_node_expected)
+    for node in node_list:
+        assert(node.text == "intCtx")
+
+
+@pytest.mark.parametrize("tools_save_l,tools_load_l,should_load", runtime_matrix_app_contexts)
+def test_save_load_app_contexts(tmpdir, tools_save_l, tools_load_l, should_load):
+
+    # Prepare environment
+    t_save = ProjectFactory.get_precook(tools_save_l)
+    t_load = ProjectFactory.get_precook(tools_load_l)
+
+    t_save_runtime_path = os.path.join(str(tmpdir), "tools-save")
+    t_load_runtime_path = os.path.join(str(tmpdir), "tools-load")
+    save_load_path = os.path.join(str(tmpdir), 'save_load')
+    validation_path = os.path.join(str(tmpdir), 'validation')
+
+    trace_name = "saved_trace"
+    trace_filename = trace_name + Settings.save_ext
+    trace_file_path = os.path.join(save_load_path, trace_filename)
+
+    validation_file_path = os.path.join(validation_path, trace_filename)
+
+    # Craft the save
+    with Run.get_runtime(t_save_runtime_path) as runtime:
+        runtime.add_project(t_save)
+
+        # Start lttng-sessiond
+        sessiond = utils.sessiond_spawn(runtime)
+
+        runtime.run("lttng create {}".format(trace_name))
+        runtime.run("lttng enable-event --jul hello")
+        runtime.run("lttng enable-event --log4j hello")
+        # NOTE:  For now there is a bug/quirk for which app context is applied
+        # everywhere. Might need to be revisited. This influence the number of
+        # node we expect in the saved file.
+        runtime.run("lttng add-context --jul --type='$app.myRetriever:intCtx'")
+        runtime.run("lttng save --output-path={}".format(save_load_path))
+
+        cp = runtime.subprocess_terminate(sessiond)
+        if cp.returncode != 0:
+            pytest.fail("Sessiond on save return code")
+
+    validate_app_context(trace_name, trace_file_path)
+
+    # Load the save
+    with Run.get_runtime(t_load_runtime_path) as runtime:
+        runtime.add_project(t_load)
+
+        # Start lttng-sessiond
+        sessiond = utils.sessiond_spawn(runtime)
+
+        cmd = "lttng load --input-path={} {}".format(save_load_path, trace_name)
+
+        if not should_load:
+            cp, out, err = runtime.run(cmd, check_return=False)
+            assert(cp.returncode != 0)
+            assert(utils.file_contains(err, ['Session configuration file validation failed']))
+            return
+
+        runtime.run(cmd)
+
+        # Since lttng list does not include context we need to re-save and
+        # validate that the contexts are presend in the newly saved file.
+        runtime.run("lttng save --output-path={}".format(validation_path))
+
+        cp = runtime.subprocess_terminate(sessiond)
+        if cp.returncode != 0:
+            pytest.fail("Sessiond on load return code")
+
+    validate_app_context(trace_name, validation_file_path)
+
+
+@pytest.mark.parametrize("tools_save_l,tools_load_l,should_load", runtime_matrix_blocking_timeout)
+def test_save_load_blocking_timeout(tmpdir, tools_save_l, tools_load_l, should_load):
+
+    # Prepare environment
+    t_save = ProjectFactory.get_precook(tools_save_l)
+    t_load = ProjectFactory.get_precook(tools_load_l)
+
+    t_save_runtime_path = os.path.join(str(tmpdir), "tools-save")
+    t_load_runtime_path = os.path.join(str(tmpdir), "tools-load")
+    save_load_path = os.path.join(str(tmpdir), 'save_load')
+
+    trace_name = "saved_trace"
+    channel_name = "my_channel"
+    trace_filename = trace_name + Settings.save_ext
+    trace_file_path = os.path.join(save_load_path, trace_filename)
+
+    blocking_timeout = 1000
+
+    # Craft the save
+    with Run.get_runtime(t_save_runtime_path) as runtime:
+        runtime.add_project(t_save)
+
+        # Start lttng-sessiond
+        sessiond = utils.sessiond_spawn(runtime)
+
+        runtime.run("lttng create {}".format(trace_name))
+        runtime.run("lttng enable-channel -u --blocking-timeout {} {}".format(blocking_timeout, channel_name))
+        runtime.run("lttng save --output-path={}".format(save_load_path))
+
+
+        cp = runtime.subprocess_terminate(sessiond)
+        if cp.returncode != 0:
+            pytest.fail("Sessiond on save return code")
+
+    assert(os.path.isfile(trace_file_path))
+
+    xpath_blocking_timeout = '/sessions/session[name="{}"]/domains/domain[type="UST"]/channels/channel[name="{}"]/blocking_timeout'.format(trace_name, channel_name)
+    node = xpath_query(trace_file_path, xpath_blocking_timeout)
+    assert(len(node) == 1)
+    assert(node[0].text == str(blocking_timeout))
+
+    # Load the save
+    with Run.get_runtime(t_load_runtime_path) as runtime:
+        runtime.add_project(t_load)
+
+        # Start lttng-sessiond
+        sessiond = utils.sessiond_spawn(runtime)
+
+        if should_load:
+            runtime.run("lttng load --input-path={} {}".format(save_load_path, trace_name))
+        else:
+            with pytest.raises(subprocess.CalledProcessError):
+                runtime.run("lttng load --input-path={} {}".format(save_load_path, trace_name))
+            cp = runtime.subprocess_terminate(sessiond)
+            if cp.returncode != 0:
+                pytest.fail("Sessiond on load return code")
+            return
+
+        cp, mi_out, err = runtime.run("lttng --mi xml list {}".format(trace_name))
+
+        cp = runtime.subprocess_terminate(sessiond)
+        if cp.returncode != 0:
+            pytest.fail("Sessiond on load return code")
+
+    assert(os.path.isfile(mi_out))
+    xpath_mi_blocking_timeout = '/command/output/sessions/session/domains/domain/channels/channel/attributes/blocking_timeout'
+    node = xpath_query(mi_out, xpath_mi_blocking_timeout)
+    assert(len(node) == 1)
+    assert(node[0].text == str(blocking_timeout))
+
+
+@pytest.mark.parametrize("tools_save_l,tools_load_l,should_load", runtime_matrix_monitor_timer_interval)
+def test_save_load_timer_interval(tmpdir, tools_save_l, tools_load_l, should_load):
+
+    # Prepare environment
+    t_save = ProjectFactory.get_precook(tools_save_l)
+    t_load = ProjectFactory.get_precook(tools_load_l)
+
+    t_save_runtime_path = os.path.join(str(tmpdir), "tools-save")
+    t_load_runtime_path = os.path.join(str(tmpdir), "tools-load")
+    save_load_path = os.path.join(str(tmpdir), 'save_load')
+
+    trace_name = "saved_trace"
+    channel_name = "my_channel"
+    trace_filename = trace_name + Settings.save_ext
+    trace_file_path = os.path.join(save_load_path, trace_filename)
+
+    monitor_timer_interval = 1000
+
+    # Craft the save
+    with Run.get_runtime(t_save_runtime_path) as runtime:
+        runtime.add_project(t_save)
+
+        # Start lttng-sessiond
+        sessiond = utils.sessiond_spawn(runtime)
+
+        runtime.run("lttng create {}".format(trace_name))
+        runtime.run("lttng enable-channel -u --monitor-timer={} {}".format(monitor_timer_interval, channel_name))
+        runtime.run("lttng save --output-path={}".format(save_load_path))
+
+        assert(os.path.isfile(trace_file_path))
+
+        cp = runtime.subprocess_terminate(sessiond)
+        if cp.returncode != 0:
+            pytest.fail("Sessiond on save return code")
+
+    assert(os.path.isfile(trace_file_path))
+
+    xpath_monitor_interval = '/sessions/session/domains/domain[type="UST"]/channels/channel/monitor_timer_interval'
+    node = xpath_query(trace_file_path, xpath_monitor_interval)
+    assert(len(node) == 1)
+    assert(node[0].text == str(monitor_timer_interval))
+
+    # Load the save
+    with Run.get_runtime(t_load_runtime_path) as runtime:
+        runtime.add_project(t_load)
+
+        # Start lttng-sessiond
+        sessiond = utils.sessiond_spawn(runtime)
+
+        if should_load:
+            runtime.run("lttng load --input-path={} {}".format(save_load_path, trace_name))
+        else:
+            with pytest.raises(subprocess.CalledProcessError):
+                runtime.run("lttng load --input-path={} {}".format(save_load_path, trace_name))
+            cp = runtime.subprocess_terminate(sessiond)
+            if cp.returncode != 0:
+                pytest.fail("Sessiond on load return code")
+            return
+
+        cp, mi_out, err = runtime.run("lttng --mi xml list {}".format(trace_name))
+
+        cp = runtime.subprocess_terminate(sessiond)
+        if cp.returncode != 0:
+            pytest.fail("Sessiond on load return code")
+
+    assert(os.path.isfile(mi_out))
+    xpath_mi = '/command/output/sessions/session/domains/domain/channels/channel/attributes/monitor_timer_interval'
+    node = xpath_query(mi_out, xpath_mi)
+    assert(len(node) == 1)
+    assert(node[0].text == str(monitor_timer_interval))
This page took 0.027174 seconds and 5 git commands to generate.