Example #1
0
def test_cc_for_cxx_does_not_inject():
    cc_for_cxx = CCForCXX({})
    cc = CC(["-std=c99", "foo.c"])

    cc_for_cxx.before_run(cc)

    assert cc.args == shlex.split("-std=c99 foo.c")
Example #2
0
def test_ignore_werror():
    ignore_werror = IgnoreWerror({})
    cc = CC(["-Wall", "-Werror", "-O3", "-Werror"])

    ignore_werror.before_run(cc)

    assert cc.args == shlex.split("-Wall -O3")
Example #3
0
def test_find_outputs_journaling(monkeypatch, tmp_path):
    journal_output = tmp_path / "journal.jsonl"
    monkeypatch.setenv("BLIGHT_JOURNAL_PATH", str(journal_output))

    store = tmp_path / "store"
    contents = b"not a real object file"
    contents_digest = hashlib.sha256(contents).hexdigest()
    dummy_foo_o = tmp_path / "foo.o"
    dummy_foo_o_store = store / f"{dummy_foo_o.name}-{contents_digest}"

    find_outputs = FindOutputs({"store": store})
    cc = CC(["-c", "foo.c", "-o", str(dummy_foo_o)])
    find_outputs.before_run(cc)
    # Pretend to be the compiler: write some junk to dummy_foo_o
    dummy_foo_o.write_bytes(contents)

    find_outputs.after_run(cc)

    outputs = find_outputs._result["outputs"]
    assert len(outputs) == 1
    assert outputs[0] == {
        "kind": OutputKind.Object.value,
        "prenormalized_path": str(dummy_foo_o),
        "path": dummy_foo_o,
        "store_path": dummy_foo_o_store,
        "content_hash": contents_digest,
    }
    assert dummy_foo_o_store.read_bytes() == contents
Example #4
0
def test_cc_for_cxx():
    cc_for_cxx = CCForCXX({})
    cc = CC(["-std=c++17", "foo.cpp"])

    cc_for_cxx.before_run(cc)

    assert cc.args == shlex.split("-x c++ -std=c++17 foo.cpp")
Example #5
0
def test_ignore_werror():
    ignore_flto = IgnoreFlto({})
    cc = CC(["-Wall", "-Werror", "-flto", "-flto=thin", "-O3"])

    ignore_flto.before_run(cc)

    assert cc.args == shlex.split("-Wall -Werror -O3")
Example #6
0
def test_find_outputs_store_no_hash(tmp_path):
    output = tmp_path / "outputs.jsonl"
    store = tmp_path / "store"
    contents = b"not a real object file"
    contents_digest = hashlib.sha256(contents).hexdigest()
    dummy_foo_o = tmp_path / "foo.o"
    # Store filename should not have its hash appended
    dummy_foo_o_store = store / dummy_foo_o.name

    find_outputs = FindOutputs({
        "output": output,
        "store": store,
        "append_hash": "false"
    })
    cc = CC(["-c", "foo.c", "-o", str(dummy_foo_o)])
    find_outputs.before_run(cc)
    # Pretend to be the compiler: write some junk to dummy_foo_o
    dummy_foo_o.write_bytes(contents)
    find_outputs.after_run(cc)

    outputs = json.loads(output.read_text())["outputs"]
    assert outputs == [{
        "kind": OutputKind.Object.value,
        "prenormalized_path": str(dummy_foo_o),
        "path": str(dummy_foo_o),
        "store_path": str(dummy_foo_o_store),
        "content_hash": contents_digest,
    }]
    assert dummy_foo_o_store.read_bytes() == contents
Example #7
0
def test_skip_strip(monkeypatch):
    monkeypatch.setenv("BLIGHT_ACTIONS", "SkipStrip")
    monkeypatch.setenv("BLIGHT_WRAPPED_STRIP", "true")

    # SkipStrip causes strip runs to be skipped
    strip = STRIP([])
    assert SkipStrip in [a.__class__ for a in strip._actions]
    assert not strip._skip_run
    strip.run()
    assert strip._skip_run

    # SkipStrip doesn't affect other tools
    cc = CC(["-v"])
    assert SkipStrip in [a.__class__ for a in cc._actions]
    assert not cc._skip_run
    cc.run()
    assert not cc._skip_run
Example #8
0
def test_record(tmp_path):
    output = tmp_path / "record.jsonl"
    record = Record({"output": output})

    record.before_run(CC(["-fake", "-flags"]))

    record_contents = json.loads(output.read_text())
    assert record_contents["wrapped_tool"] == shutil.which("cc")
    assert record_contents["args"] == ["-fake", "-flags"]
Example #9
0
def test_find_outputs(tmp_path):
    output = tmp_path / "outputs.jsonl"

    find_outputs = FindOutputs({"output": output})
    cc = CC(["-o", "foo", "foo.c"])
    find_outputs.before_run(cc)

    outputs = json.loads(output.read_text())["outputs"]
    assert outputs[OutputKind.Executable.value] == [str(cc.cwd / "foo")]
Example #10
0
 def before_run(self, tool: CC) -> None:  # type: ignore
     # NOTE(ww): Currently, the only way we check whether CC is being used
     # as a C++ compiler is by checking whether one of the `-std=c++XX`
     # flags has been passed. This won't catch all cases; someone could use
     # CC as a C++ compiler with the default C++ standard.
     # Other options for detecting this:
     # * Check for common C++-only linkages, like -lstdc++fs
     # * Check whether tool.inputs contains files that look like C++
     if tool.std.is_cxxstd():
         tool.args[:0] = ["-x", "c++"]
Example #11
0
def test_ignore_flags():
    ignore_flags = IgnoreFlags({"FLAGS": "-Wextra -ffunction-sections"})

    for tool in [CC, CXX]:
        tool = CC([
            "-Wall", "-ffunction-sections", "-O3", "-ffunction-sections",
            "-Wextra"
        ])
        ignore_flags.before_run(tool)
        assert tool.args == shlex.split("-Wall -O3")
Example #12
0
def test_record(tmp_path):
    output = tmp_path / "record.jsonl"
    record = Record({"output": output})

    record.after_run(CC(["-fake", "-flags"]), run_skipped=False)

    record_contents = json.loads(output.read_text())
    assert record_contents["wrapped_tool"] == shutil.which("cc")
    assert record_contents["args"] == ["-fake", "-flags"]
    assert not record_contents["run_skipped"]
Example #13
0
def test_inject_flags():
    inject_flags = InjectFlags({
        "CFLAGS": "-more -flags",
        "CXXFLAGS": "-these -are -ignored",
        "CPPFLAGS": "-foo"
    })
    cc = CC(["-fake", "-flags"])

    inject_flags.before_run(cc)

    assert cc.args == shlex.split("-fake -flags -more -flags -foo")
Example #14
0
def test_find_outputs_multiple(tmp_path):
    fake_cs = [tmp_path / fake_c for fake_c in ["foo.c", "bar.c", "baz.c"]]
    [fake_c.touch() for fake_c in fake_cs]

    output = tmp_path / "outputs.jsonl"

    find_outputs = FindOutputs({"output": output})
    cc = CC(["-c", *[str(fake_c) for fake_c in fake_cs]])
    find_outputs.before_run(cc)

    outputs = json.loads(output.read_text())["outputs"]
    assert outputs[OutputKind.Object.value] == [
        str(cc.cwd / fake_c.with_suffix(".o").name) for fake_c in fake_cs
    ]
Example #15
0
def test_inject_linker_flags():
    inject_flags = InjectFlags({
        "CFLAGS": "-cc-flags",
        "CFLAGS_LINKER": "-c-linker-flags",
        "CXXFLAGS": "-cxx-flags",
        "CXXFLAGS_LINKER": "-cxx-linker-flags",
    })

    cc_nolink = CC(["-c"])
    cc_link = CC(["-fake", "-flags"])
    cxx_nolink = CXX(["-c"])
    cxx_link = CXX(["-fake", "-flags"])

    inject_flags.before_run(cc_nolink)
    inject_flags.before_run(cc_link)
    inject_flags.before_run(cxx_nolink)
    inject_flags.before_run(cxx_link)

    assert cc_nolink.args == shlex.split("-c -cc-flags")
    assert cc_link.args == shlex.split(
        "-fake -flags -cc-flags -c-linker-flags")
    assert cxx_nolink.args == shlex.split("-c -cxx-flags")
    assert cxx_link.args == shlex.split(
        "-fake -flags -cxx-flags -cxx-linker-flags")
Example #16
0
def test_find_outputs_annoying_so_prefixes(tmp_path, soname):
    output = tmp_path / "outputs.jsonl"

    find_outputs = FindOutputs({"output": output})
    cc = CC(["-shared", "-o", soname, "foo.c"])
    find_outputs.before_run(cc)
    find_outputs.after_run(cc)

    outputs = json.loads(output.read_text())["outputs"]
    assert outputs == [{
        "kind": OutputKind.SharedLibrary.value,
        "prenormalized_path": soname,
        "path": str(cc.cwd / soname),
        "store_path": None,
        "content_hash": None,
    }]
Example #17
0
def test_find_outputs_handles_a_out(tmp_path):
    output = tmp_path / "outputs.jsonl"

    find_outputs = FindOutputs({"output": output})
    cc = CC(["foo.c"])
    find_outputs.before_run(cc)
    find_outputs.after_run(cc)

    outputs = json.loads(output.read_text())["outputs"]
    assert outputs == [{
        "kind": OutputKind.Executable.value,
        "prenormalized_path": "a.out",
        "path": str(cc.cwd / "a.out"),
        "store_path": None,
        "content_hash": None,
    }]
Example #18
0
def test_find_outputs_store_output_does_not_exist(tmp_path):
    output = tmp_path / "outputs.jsonl"
    store = tmp_path / "store"
    dummy_foo_o = tmp_path / "foo.o"

    find_outputs = FindOutputs({"output": output, "store": store})
    cc = CC(["-c", "foo.c", "-o", str(dummy_foo_o)])
    find_outputs.before_run(cc)
    find_outputs.after_run(cc)

    outputs = json.loads(output.read_text())["outputs"]
    assert outputs == [{
        "kind": OutputKind.Object.value,
        "prenormalized_path": str(dummy_foo_o),
        "path": str(dummy_foo_o),
        "store_path": None,
        "content_hash": None,
    }]
Example #19
0
def test_find_outputs_multiple(tmp_path):
    fake_cs = [tmp_path / fake_c for fake_c in ["foo.c", "bar.c", "baz.c"]]
    [fake_c.touch() for fake_c in fake_cs]

    output = tmp_path / "outputs.jsonl"

    find_outputs = FindOutputs({"output": output})
    cc = CC(["-c", *[str(fake_c) for fake_c in fake_cs]])
    find_outputs.before_run(cc)
    find_outputs.after_run(cc)

    outputs = json.loads(output.read_text())["outputs"]
    assert outputs == [{
        "kind": OutputKind.Object.value,
        "prenormalized_path": fake_c.with_suffix(".o").name,
        "path": str(cc.cwd / fake_c.with_suffix(".o").name),
        "store_path": None,
        "content_hash": None,
    } for fake_c in fake_cs]
Example #20
0
def test_find_inputs_journaling(monkeypatch, tmp_path):
    journal_output = tmp_path / "journal.jsonl"
    monkeypatch.setenv("BLIGHT_JOURNAL_PATH", str(journal_output))

    foo_input = (tmp_path / "foo.c").resolve()
    foo_input.touch()

    find_inputs = FindInputs({})
    cc = CC(["-c", str(foo_input), "-o", "foo"])
    find_inputs.before_run(cc)
    find_inputs.after_run(cc)

    inputs = find_inputs._result["inputs"]
    assert len(inputs) == 1
    assert inputs[0] == {
        "kind": InputKind.Source.value,
        "prenormalized_path": str(foo_input),
        "path": foo_input,
        "store_path": None,
        "content_hash": None,
    }
Example #21
0
def test_find_inputs(tmp_path):
    output = tmp_path / "outputs.jsonl"

    foo_input = (tmp_path / "foo.c").resolve()
    foo_input.touch()

    find_inputs = FindInputs({"output": output})
    cwd_path = Path(os.getcwd()).resolve()
    os.chdir(tmp_path)
    cc = CC(["-o", "foo", "foo.c"])
    os.chdir(cwd_path)
    find_inputs.before_run(cc)
    find_inputs.after_run(cc)

    inputs = json.loads(output.read_text())["inputs"]
    assert inputs == [
        {
            "kind": InputKind.Source.value,
            "prenormalized_path": "foo.c",
            "path": str(foo_input),
            "store_path": None,
            "content_hash": None,
        }
    ]
Example #22
0
def test_embed_bitcode():
    embed_bitcode = EmbedBitcode({})
    cc = CC(["-o", "foo"])
    embed_bitcode.before_run(cc)

    assert cc.args[0] == "-fembed-bitcode"