blob: d5b3c353063a0e8b3ebad412ec4ead49c4c721ac [file] [log] [blame]
#!/usr/bin/env python3.8
# 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:
python3 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()