Repository: mandiant/capa
File: tests/test_scripts.py (Python)

Code before:


def get_rules_path():
    return os.path.join(CD, "..", "rules")


def get_rule_path():
    return os.path.join(get_rules_path(), "lib", "allocate-memory.yml")


@pytest.mark.parametrize(
    # test detect_duplicate_features.py script for 3 cases
    # - New rule isn't a valid rule
    # - New rule file name doesn't ends with .yml
    # - Checks if number of overlaps found for a test rule are correct
    "overlap_script,args,expected",
    [
        pytest.param("detect_duplicate_features.py", [get_rules_path(), "rules/.github/workflows/sync.yml"], 1),
        pytest.param("detect_duplicate_features.py", [get_rules_path(), "rules/.github/workflows/sync.ym"], 1),
        pytest.param(
            "detect_duplicate_features.py",
            [
                get_rules_path(),
                os.path.join(get_rules_path(), "collection/credit-card/parse-credit-card-information.yml"),
            ],
            49,
        ),
    ],
)
def test_overlap_scripts(overlap_script, args, expected):
    script_path = get_script_path(overlap_script)
    p = run_program(script_path, args)
    assert p.returncode == expected


@pytest.mark.parametrize(
    "script,args",
    [
        pytest.param("capa2yara.py", [get_rules_path()]),
        pytest.param("capafmt.py", [get_rule_path()]),
        # not testing lint.py as it runs regularly anyway
        pytest.param("match-function-id.py", [get_file_path()]),
        pytest.param("show-capabilities-by-function.py", [get_file_path()]),
        pytest.param("show-features.py", [get_file_path()]),
        pytest.param("show-features.py", ["-F", "0x407970", get_file_path()]),
        pytest.param("capa_as_library.py", [get_file_path()]),
    ],
)
def test_scripts(script, args):
    script_path = get_script_path(script)
    p = run_program(script_path, args)

Review comment (suggestion):
I'm afraid this could change when we update rules, so I'd say we better create a test rule set and rule like we do in the test_rules and test that here. We don't have to parametrize it and can just add it verbatim inline.

Code after:
def get_file_path():
    return os.path.join(CD, "data", "9324d1a8ae37a36ae560c37448c9705a.exe_")


def get_rules_path():
    return os.path.join(CD, "..", "rules")


def get_rule_path():
    return os.path.join(get_rules_path(), "lib", "allocate-memory.yml")


@pytest.mark.parametrize(
    "script,args",
    [
        pytest.param("capa2yara.py", [get_rules_path()]),
        pytest.param("capafmt.py", [get_rule_path()]),
        # not testing lint.py as it runs regularly anyway
        pytest.param("match-function-id.py", [get_file_path()]),
        pytest.param("show-capabilities-by-function.py", [get_file_path()]),
        pytest.param("show-features.py", [get_file_path()]),
        pytest.param("show-features.py", ["-F", "0x407970", get_file_path()]),
        pytest.param("capa_as_library.py", [get_file_path()]),
    ],
)
def test_scripts(script, args):
    script_path = get_script_path(script)
    p = run_program(script_path, args)
    assert p.returncode == 0


def test_bulk_process(tmpdir):
    # create test directory to recursively analyze
    t = tmpdir.mkdir("test")
    with open(os.path.join(CD, "data", "ping_täst.exe_"), "rb") as f:
        t.join("test.exe_").write_binary(f.read())

    p = run_program(get_script_path("bulk-process.py"), [t.dirname])
    assert p.returncode == 0


def run_program(script_path, args):
    args = [sys.executable] + [script_path] + args
    print(f"running: '{args}'")
    return subprocess.run(args, stdout=subprocess.PIPE)


def test_proto_conversion(tmpdir):
    t = tmpdir.mkdir("proto-test")

    json = os.path.join(CD, "data", "rd", "Practical Malware Analysis Lab 01-01.dll_.json")