blob: 2396a9e97a6e65f034cae2b6e7f39b056b8d5bed [file] [log] [blame]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2021 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Unit test for main.py.
To manually run this test:
fuchsia-vendored-python main_test.py
"""
import json
import os
import subprocess
import tempfile
import time
import unittest
import unittest.mock as mock
import main
_TARGET_1 = "foo.cc.o"
_TARGET_2 = "baz/bar.cc.o"
_TARGET_3 = "biz/fuzz.cc.o"
_TARGETS = [_TARGET_1, _TARGET_2, _TARGET_3]
def setup_compdb_and_fs(directory, targets, changed):
compdb = []
changed_comp_db = []
# Setup targets
for target in targets:
if not target.endswith(".o"):
raise Exception(
"Expected all targets to end with '.o', "
"but received %s." % (target)
)
# Add the target to the compdb
target_def = {
"file": target[:-2],
"directory": directory,
"command": "clang++ -o %s" % (target),
}
compdb.append(target_def)
# If it is expected to change, add the target to the changed compdb
if target in changed:
changed_comp_db.append(target_def)
# Make the placeholder file to set the last modified time before fx ninja
target_path = os.path.join(directory, target)
os.makedirs(os.path.dirname(target_path), exist_ok=True)
with open(target_path, "w") as f:
f.write("test placeholder")
return (compdb, changed_comp_db)
class RunCsaHelperTest(unittest.TestCase):
def helper(self, temp_dir, targets, changed):
ninja_path = "tmp/ninja"
out_dir = os.path.join(temp_dir, "foo/bar")
# Set up the output directory and compdbs
compdb, expected_changed_compdb = setup_compdb_and_fs(
out_dir, targets, changed
)
# Write the compdb
input_file = os.path.join(temp_dir, "compile_commands.json")
with open(input_file, "w") as in_file:
json.dump(compdb, in_file)
# Mock out the xargs fx ninja call
fake_ninja = FakeNinja(out_dir, changed)
with mock.patch("subprocess.run") as mock_run:
mock_run.side_effect = fake_ninja.run
output_file = os.path.join(
temp_dir, "modified_compile_commands.json"
)
args = [
"--input",
input_file,
"--output",
output_file,
"--ninja",
ninja_path,
]
# Ensure the script succeeded
self.assertEqual(0, main.main(args))
# Check that the output compdb contains the files that were modified
with open(output_file, "r") as out_file:
self.assertEqual(
json.dumps(expected_changed_compdb, indent=2),
out_file.read(),
)
def test_no_changed_files(self):
with tempfile.TemporaryDirectory() as temp_dir:
self.helper(temp_dir, _TARGETS, [])
def test_some_changed_files(self):
with tempfile.TemporaryDirectory() as temp_dir:
self.helper(temp_dir, _TARGETS, [_TARGET_1, _TARGET_3])
def test_all_changed_files(self):
with tempfile.TemporaryDirectory() as temp_dir:
self.helper(temp_dir, _TARGETS, [_TARGET_1, _TARGET_2, _TARGET_3])
class FakeNinja(object):
def __init__(self, directory, files_to_update):
self.directory = directory
self.files_to_update = files_to_update
return
def run(self, *argv, **kwargs):
del argv
del kwargs
# Sleep for a second so that the modified time check changes
time.sleep(1)
for file_to_update in self.files_to_update:
target_path = os.path.join(self.directory, file_to_update)
if not os.path.exists(target_path):
raise Exception(
"Expected path %s to already exist." % (target_path)
)
with open(target_path, "w") as f:
f.write("updated")
return subprocess.CompletedProcess(args=[], returncode=0, stdout=b"")
if __name__ == "__main__":
unittest.main()