From 460a46b534b9c12f6870569d41f11f730b8185ad Mon Sep 17 00:00:00 2001 From: Stephen Wakely Date: Fri, 11 Oct 2024 11:49:43 +0100 Subject: [PATCH 1/2] [omnibus] Include `libjemalloc.so.2` in the Agent package (#29628) Co-authored-by: alopezz --- omnibus/config/software/datadog-agent.rb | 4 +++ omnibus/config/software/libjemalloc.rb | 39 ++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 omnibus/config/software/libjemalloc.rb diff --git a/omnibus/config/software/datadog-agent.rb b/omnibus/config/software/datadog-agent.rb index adfd26bd5671c..dde0e60bf65d9 100644 --- a/omnibus/config/software/datadog-agent.rb +++ b/omnibus/config/software/datadog-agent.rb @@ -16,6 +16,10 @@ dependency "openscap" if linux_target? and !arm7l_target? and !heroku_target? # Security-agent dependency, not needed for Heroku +# Alternative memory allocator which has better support for memory allocated by cgo calls, +# especially at higher thread counts. +dependency "libjemalloc" if linux_target? + dependency 'agent-dependencies' dependency 'datadog-agent-dependencies' diff --git a/omnibus/config/software/libjemalloc.rb b/omnibus/config/software/libjemalloc.rb new file mode 100644 index 0000000000000..d217968605585 --- /dev/null +++ b/omnibus/config/software/libjemalloc.rb @@ -0,0 +1,39 @@ +# Unless explicitly stated otherwise all files in this repository are licensed +# under the Apache License Version 2.0. +# This product includes software developed at Datadog (https:#www.datadoghq.com/). +# Copyright 2022-present Datadog, Inc. + +name "libjemalloc" +default_version "5.3.0" + +version "5.3.0" do + source sha256: "ef6f74fd45e95ee4ef7f9e19ebe5b075ca6b7fbe0140612b2a161abafb7ee179" +end + +ship_source_offer true + +source url:"https://github.com/jemalloc/jemalloc/archive/refs/tags/#{version}.tar.gz", + extract: :seven_zip + +relative_path "jemalloc-#{version}" + +build do + license "BSD-2-Clause" + license_file "./COPYING" + + env = with_standard_compiler_flags + + command "autoconf" + + # This builds libjemalloc.so.2 + configure_options = [ + "--disable-debug", + "--disable-stats", + "--disable-fill", + "--disable-prof", + "--disable-static", + ] + configure(*configure_options, env: env) + command "make -j #{workers}", env: env + command "make install_lib_shared" +end From b2159bf6c84fc845b5c1a39a1f838d37d4a29bce Mon Sep 17 00:00:00 2001 From: Kevin Fairise <132568982+KevinFairise2@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:37:32 +0200 Subject: [PATCH 2/2] Move testing related function to a dedicated lib + move unit tests (#30017) --- tasks/libs/common/junit_upload_core.py | 7 +- tasks/libs/testing/flakes.py | 58 ++++++++++++++++ tasks/testwasher.py | 52 +------------- tasks/unit_tests/flakes_tests.py | 96 ++++++++++++++++++++++++++ tasks/unit_tests/testwasher_tests.py | 71 ------------------- 5 files changed, 163 insertions(+), 121 deletions(-) create mode 100644 tasks/libs/testing/flakes.py create mode 100644 tasks/unit_tests/flakes_tests.py diff --git a/tasks/libs/common/junit_upload_core.py b/tasks/libs/common/junit_upload_core.py index fdbd052760974..5d2508e055bc6 100644 --- a/tasks/libs/common/junit_upload_core.py +++ b/tasks/libs/common/junit_upload_core.py @@ -23,6 +23,7 @@ GITHUB_JIRA_MAP, GITHUB_SLACK_MAP, ) +from tasks.libs.testing.flakes import get_tests_family, is_known_flaky_test from tasks.modules import DEFAULT_MODULES E2E_INTERNAL_ERROR_STRING = "E2E INTERNAL ERROR" @@ -210,7 +211,11 @@ def split_junitxml(root_dir: Path, xml_path: Path, codeowners, flaky_tests): # Flag the test as known flaky if gotestsum already knew it for test_case in suite.iter("testcase"): test_name = "/".join([test_case.attrib["classname"], test_case.attrib["name"]]) - test_case.attrib["agent_is_known_flaky"] = "true" if test_name in flaky_tests else "false" + if is_known_flaky_test(test_name, flaky_tests, get_tests_family(list(flaky_tests))): + test_case.attrib["agent_is_known_flaky"] = "true" + print("KNOWN FLAKY:", test_name) + else: + test_case.attrib["agent_is_known_flaky"] = "false" xml.getroot().append(suite) diff --git a/tasks/libs/testing/flakes.py b/tasks/libs/testing/flakes.py new file mode 100644 index 0000000000000..1630e509677d2 --- /dev/null +++ b/tasks/libs/testing/flakes.py @@ -0,0 +1,58 @@ +def get_tests_family_if_failing_tests(test_name_list, failing_tests: set): + """Get the parent tests of a list of tests only if the marked test is failing + + For example with the test ["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestCPU"] + this method should return the set{"TestEKSSuite/TestCPU/TestCPUUtilization", "TestEKSSuite/TestCPU", "TestEKSSuite", "TestKindSuite/TestCPU", "TestKindSuite"} + if TestKindSuite/TestCPU and TestEKSSuite/TestCPU/TestCPUUtilization are failing + Another example, with the test ["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestCPU"] + if only TestKindSuite/TestCPU is failing, the method should return the set{"TestKindSuite/TestCPU", "TestKindSuite"} + + Args: + test_name_list (list): List of test names to get the parent tests from + failing_tests (set): Set of tests that are failing + """ + test_name_set = set(test_name_list) + marked_tests_failing = failing_tests.intersection(test_name_set) + return get_tests_family(list(marked_tests_failing)) + + +def get_tests_family(test_name_list): + """Get the parent tests of a list of tests + + Get the parent tests of a list of tests + For example with the test ["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestCPU"] + this method should return the set{"TestEKSSuite/TestCPU/TestCPUUtilization", "TestEKSSuite/TestCPU", "TestEKSSuite", "TestKindSuite/TestCPU", "TestKindSuite"} + + Args: + test_name_list (list): List of test names to get the parent tests from + + """ + test_family = set(test_name_list) + for test_name in test_name_list: + while test_name.count('/') > 0: + test_name = test_name.rsplit('/', 1)[0] + test_family.add(test_name) + return test_family + + +def is_known_flaky_test(failing_test, known_flaky_tests, known_flaky_tests_parents): + """Check if a test is known to be flaky + + If a test is a parent of a test that is known to be flaky, the test should be considered flaky + For example: + - if TestEKSSuite/TestCPU is known to be flaky, TestEKSSuite/TestCPU/TestCPUUtilization should be considered flaky + - if TestEKSSuite/TestCPU is known to be flaky, TestEKSSuite should be considered flaky unless TestEKSSuite/TestCPU is not failing + - if TestEKSSuite/TestCPU is known to be flaky, TestEKSSuite/TestMemory should not be considered flaky + + Args: + failing_test (str): The test that is failing + known_flaky_tests (set): Set of tests that are known to be flaky + known_flaky_tests_parents (set): Set of tests that are parent of a test that is known to be flaky + """ + + failing_test_parents = get_tests_family([failing_test]) + + if any(parent in known_flaky_tests for parent in failing_test_parents): + return True + + return failing_test in known_flaky_tests_parents diff --git a/tasks/testwasher.py b/tasks/testwasher.py index b3ceb6d6c8e09..93e74d997ee50 100644 --- a/tasks/testwasher.py +++ b/tasks/testwasher.py @@ -11,6 +11,7 @@ resolve_gitlab_ci_configuration, ) from tasks.libs.common.utils import gitlab_section +from tasks.libs.testing.flakes import get_tests_family_if_failing_tests, is_known_flaky_test from tasks.test_core import ModuleTestResult FLAKY_TEST_INDICATOR = "flakytest: this is a known flaky test" @@ -40,11 +41,11 @@ def get_non_flaky_failing_tests(self, failing_tests: dict, flaky_marked_tests: d for package, tests in failing_tests.items(): non_flaky_failing_tests_in_package = set() - known_flaky_tests_parents = self.get_tests_family_if_failing_tests( + known_flaky_tests_parents = get_tests_family_if_failing_tests( all_known_flakes[package], failing_tests[package] ) for failing_test in tests: - if not self.is_known_flaky_test(failing_test, all_known_flakes[package], known_flaky_tests_parents): + if not is_known_flaky_test(failing_test, all_known_flakes[package], known_flaky_tests_parents): non_flaky_failing_tests_in_package.add(failing_test) if non_flaky_failing_tests_in_package: non_flaky_failing_tests[package] = non_flaky_failing_tests_in_package @@ -125,53 +126,6 @@ def process_module_results(self, module_results: list[ModuleTestResult]): return should_succeed - def is_known_flaky_test(self, failing_test, known_flaky_tests, known_flaky_tests_parents): - """ - Check if a test is known to be flaky - The method should be called with the following arguments: - - failing_test: the test that is failing - - known_flaky_tests: the set of tests that are known to be flaky - - known_flaky_tests_parents: the set of tests that are ancestors of a known flaky test, thus would fail when the flaky leaf test fails - If a test is a parent of a test that is known to be flaky, the test should be considered flaky - For example: - - if TestEKSSuite/TestCPU is known to be flaky, TestEKSSuite/TestCPU/TestCPUUtilization should be considered flaky - - if TestEKSSuite/TestCPU is known to be flaky, TestEKSSuite should be considered flaky unless TestEKSSuite/TestCPU is not failing - - if TestEKSSuite/TestCPU is known to be flaky, TestEKSSuite/TestMemory should not be considered flaky - """ - - failing_test_parents = self.get_tests_family([failing_test]) - - if any(parent in known_flaky_tests for parent in failing_test_parents): - return True - - return failing_test in known_flaky_tests_parents - - def get_tests_family_if_failing_tests(self, test_name_list, failing_tests: set): - """ - Get the parent tests of a list of tests only if the marked test is failing - For example with the test ["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestCPU"] - this method should return the set{"TestEKSSuite/TestCPU/TestCPUUtilization", "TestEKSSuite/TestCPU", "TestEKSSuite", "TestKindSuite/TestCPU", "TestKindSuite"} - if TestKindSuite/TestCPU and TestEKSSuite/TestCPU/TestCPUUtilization are failing - Another example, with the test ["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestCPU"] - if only TestKindSuite/TestCPU is failing, the method should return the set{"TestKindSuite/TestCPU", "TestKindSuite"} - """ - test_name_set = set(test_name_list) - marked_tests_failing = failing_tests.intersection(test_name_set) - return self.get_tests_family(list(marked_tests_failing)) - - def get_tests_family(self, test_name_list): - """ - Get the parent tests of a list of tests - For example with the test ["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestCPU"] - this method should return the set{"TestEKSSuite/TestCPU/TestCPUUtilization", "TestEKSSuite/TestCPU", "TestEKSSuite", "TestKindSuite/TestCPU", "TestKindSuite"} - """ - test_family = set(test_name_list) - for test_name in test_name_list: - while test_name.count('/') > 0: - test_name = test_name.rsplit('/', 1)[0] - test_family.add(test_name) - return test_family - @task def generate_flake_finder_pipeline(ctx, n=3): diff --git a/tasks/unit_tests/flakes_tests.py b/tasks/unit_tests/flakes_tests.py new file mode 100644 index 0000000000000..39ff6c787be0c --- /dev/null +++ b/tasks/unit_tests/flakes_tests.py @@ -0,0 +1,96 @@ +import unittest + +from tasks.libs.testing.flakes import get_tests_family, get_tests_family_if_failing_tests, is_known_flaky_test + + +class TestGetTestParents(unittest.TestCase): + def test_get_tests_parents(self): + parents = get_tests_family(["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestKind"]) + self.assertEqual( + parents, + { + "TestEKSSuite", + "TestEKSSuite/TestCPU", + "TestEKSSuite/TestCPU/TestCPUUtilization", + "TestKindSuite", + "TestKindSuite/TestKind", + }, + ) + + def test_get_test_parents_empty(self): + parents = get_tests_family([]) + self.assertEqual( + parents, + set(), + ) + + def test_get_test_parents_failing_no_failing_tests(self): + parents = get_tests_family_if_failing_tests(["TestEKSSuite/TestCPU/TestCPUUtilization"], set()) + self.assertEqual( + parents, + set(), + ) + + def test_get_test_parents_failing_all_failing_tests(self): + parents = get_tests_family_if_failing_tests( + ["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestCPU"], + {"TestKindSuite/TestCPU", "TestEKSSuite/TestCPU/TestCPUUtilization"}, + ) + self.assertEqual( + parents, + { + "TestEKSSuite", + "TestEKSSuite/TestCPU", + "TestEKSSuite/TestCPU/TestCPUUtilization", + "TestKindSuite", + "TestKindSuite/TestCPU", + }, + ) + + def test_get_test_parents_failing_some_failing_tests(self): + parents = get_tests_family_if_failing_tests( + ["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestCPU"], {"TestKindSuite/TestCPU"} + ) + self.assertEqual( + parents, + { + "TestKindSuite", + "TestKindSuite/TestCPU", + }, + ) + + +class TestIsKnownFlake(unittest.TestCase): + def test_known_flake(self): + is_known_flaky = is_known_flaky_test( + "TestEKSSuite/mario", {"TestEKSSuite/mario"}, {"TestEKSSuite", "TestEKSSuite/mario"} + ) + self.assertTrue(is_known_flaky) + + def test_known_flake_parent_failing(self): + is_known_flaky = is_known_flaky_test( + "TestEKSSuite", {"TestEKSSuite/mario"}, {"TestEKSSuite", "TestEKSSuite/mario"} + ) + self.assertTrue(is_known_flaky) + + def test_known_flake_parent_failing_2(self): + is_known_flaky = is_known_flaky_test( + "TestEKSSuite/mario", + {"TestEKSSuite/mario/luigi"}, + {"TestEKSSuite", "TestEKSSuite/mario", "TestEKSSuite/mario/luigi"}, + ) + self.assertTrue(is_known_flaky) + + def test_not_known_flake(self): + is_known_flaky = is_known_flaky_test( + "TestEKSSuite/luigi", {"TestEKSSuite/mario"}, {"TestEKSSuite", "TestEKSSuite/mario"} + ) + self.assertFalse(is_known_flaky) + + def test_not_known_flake_ambiguous_start(self): + is_known_flaky = is_known_flaky_test("TestEKSSuiteVM/mario", {"TestEKSSuite/mario"}, {"TestEKSSuite"}) + self.assertFalse(is_known_flaky) + + def test_not_known_flake_ambiguous_start_2(self): + is_known_flaky = is_known_flaky_test("TestEKSSuite/mario", {"TestEKSSuiteVM/mario"}, {"TestEKSSuiteVM"}) + self.assertFalse(is_known_flaky) diff --git a/tasks/unit_tests/testwasher_tests.py b/tasks/unit_tests/testwasher_tests.py index 1d644e6d02880..8b25537454e02 100644 --- a/tasks/unit_tests/testwasher_tests.py +++ b/tasks/unit_tests/testwasher_tests.py @@ -65,7 +65,6 @@ def test_should_not_be_considered_flaky(self): non_flaky_failing_tests = test_washer.get_non_flaky_failing_tests( failing_tests=failing_tests, flaky_marked_tests=marked_flaky_tests ) - print("TOTOTO", non_flaky_failing_tests) self.assertEqual( non_flaky_failing_tests, {"github.com/DataDog/datadog-agent/test/new-e2e/tests/containers": {"TestEKSSuite"}}, @@ -133,73 +132,3 @@ def test_empty_yaml(self): merged_flakes, {"nintendo": {"mario", "luigi"}}, ) - - -class TestGetTestParents(unittest.TestCase): - def test_get_tests_parents(self): - test_washer = TestWasher() - parents = test_washer.get_tests_family(["TestEKSSuite/TestCPU/TestCPUUtilization", "TestKindSuite/TestKind"]) - self.assertEqual( - parents, - { - "TestEKSSuite", - "TestEKSSuite/TestCPU", - "TestEKSSuite/TestCPU/TestCPUUtilization", - "TestKindSuite", - "TestKindSuite/TestKind", - }, - ) - - def test_get_test_parents_empty(self): - test_washer = TestWasher() - parents = test_washer.get_tests_family([]) - self.assertEqual( - parents, - set(), - ) - - -class TestIsKnownFlake(unittest.TestCase): - def test_known_flake(self): - test_washer = TestWasher() - is_known_flaky = test_washer.is_known_flaky_test( - "TestEKSSuite/mario", {"TestEKSSuite/mario"}, {"TestEKSSuite", "TestEKSSuite/mario"} - ) - self.assertTrue(is_known_flaky) - - def test_known_flake_parent_failing(self): - test_washer = TestWasher() - is_known_flaky = test_washer.is_known_flaky_test( - "TestEKSSuite", {"TestEKSSuite/mario"}, {"TestEKSSuite", "TestEKSSuite/mario"} - ) - self.assertTrue(is_known_flaky) - - def test_known_flake_parent_failing_2(self): - test_washer = TestWasher() - is_known_flaky = test_washer.is_known_flaky_test( - "TestEKSSuite/mario", - {"TestEKSSuite/mario/luigi"}, - {"TestEKSSuite", "TestEKSSuite/mario", "TestEKSSuite/mario/luigi"}, - ) - self.assertTrue(is_known_flaky) - - def test_not_known_flake(self): - test_washer = TestWasher() - is_known_flaky = test_washer.is_known_flaky_test( - "TestEKSSuite/luigi", {"TestEKSSuite/mario"}, {"TestEKSSuite", "TestEKSSuite/mario"} - ) - self.assertFalse(is_known_flaky) - - def test_not_known_flake_ambiguous_start(self): - test_washer = TestWasher() - is_known_flaky = test_washer.is_known_flaky_test( - "TestEKSSuiteVM/mario", {"TestEKSSuite/mario"}, {"TestEKSSuite"} - ) - self.assertFalse(is_known_flaky) - - def test_not_known_flake_ambiguous_start_2(self): - test_washer = TestWasher() - is_known_flaky = test_washer.is_known_flaky_test( - "TestEKSSuite/mario", {"TestEKSSuiteVM/mario"}, {"TestEKSSuiteVM"} - ) - self.assertFalse(is_known_flaky)