1# Copyright 2020 Google LLC 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# http://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14"""Tests the functionality of the utils module's functions""" 15 16import os 17import tempfile 18import unittest 19from unittest import mock 20 21import utils 22import helper 23 24EXAMPLE_PROJECT = 'example' 25 26TEST_OUT_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), 27 'cifuzz', 'test_data', 'out') 28 29 30class IsFuzzTargetLocalTest(unittest.TestCase): 31 """Tests the is_fuzz_target_local function.""" 32 33 def test_invalid_filepath(self): 34 """Tests the function with an invalid file path.""" 35 is_local = utils.is_fuzz_target_local('not/a/real/file') 36 self.assertFalse(is_local) 37 is_local = utils.is_fuzz_target_local('') 38 self.assertFalse(is_local) 39 is_local = utils.is_fuzz_target_local(' ') 40 self.assertFalse(is_local) 41 42 def test_valid_filepath(self): 43 """Checks is_fuzz_target_local function with a valid filepath.""" 44 45 is_local = utils.is_fuzz_target_local( 46 os.path.join(TEST_OUT_DIR, 'example_crash_fuzzer')) 47 self.assertTrue(is_local) 48 is_local = utils.is_fuzz_target_local(TEST_OUT_DIR) 49 self.assertFalse(is_local) 50 51 52class GetFuzzTargetsTest(unittest.TestCase): 53 """Tests the get_fuzz_targets function.""" 54 55 def test_valid_filepath(self): 56 """Tests that fuzz targets can be retrieved once the fuzzers are built.""" 57 fuzz_targets = utils.get_fuzz_targets(TEST_OUT_DIR) 58 crash_fuzzer_path = os.path.join(TEST_OUT_DIR, 'example_crash_fuzzer') 59 nocrash_fuzzer_path = os.path.join(TEST_OUT_DIR, 'example_nocrash_fuzzer') 60 self.assertCountEqual(fuzz_targets, 61 [crash_fuzzer_path, nocrash_fuzzer_path]) 62 63 # Testing on a arbitrary directory with no fuzz targets in it. 64 fuzz_targets = utils.get_fuzz_targets( 65 os.path.join(helper.OSS_FUZZ_DIR, 'infra', 'travis')) 66 self.assertFalse(fuzz_targets) 67 68 def test_invalid_filepath(self): 69 """Tests what get_fuzz_targets return when invalid filepath is used.""" 70 fuzz_targets = utils.get_fuzz_targets('not/a/valid/file/path') 71 self.assertFalse(fuzz_targets) 72 73 74class ExecuteTest(unittest.TestCase): 75 """Tests the execute function.""" 76 77 def test_valid_command(self): 78 """Tests that execute can produce valid output.""" 79 with tempfile.TemporaryDirectory() as tmp_dir: 80 out, err, err_code = utils.execute(['ls', '.'], 81 location=tmp_dir, 82 check_result=False) 83 self.assertEqual(err_code, 0) 84 self.assertEqual(err, '') 85 self.assertEqual(out, '') 86 out, err, err_code = utils.execute(['mkdir', 'tmp'], 87 location=tmp_dir, 88 check_result=False) 89 self.assertEqual(err_code, 0) 90 self.assertEqual(err, '') 91 self.assertEqual(out, '') 92 out, err, err_code = utils.execute(['ls', '.'], 93 location=tmp_dir, 94 check_result=False) 95 self.assertEqual(err_code, 0) 96 self.assertEqual(err, '') 97 self.assertEqual(out, 'tmp\n') 98 99 def test_error_command(self): 100 """Tests that execute can correctly surface errors.""" 101 with tempfile.TemporaryDirectory() as tmp_dir: 102 out, err, err_code = utils.execute(['ls', 'notarealdir'], 103 location=tmp_dir, 104 check_result=False) 105 self.assertEqual(err_code, 2) 106 self.assertIsNotNone(err) 107 self.assertEqual(out, '') 108 with self.assertRaises(RuntimeError): 109 out, err, err_code = utils.execute(['ls', 'notarealdir'], 110 location=tmp_dir, 111 check_result=True) 112 113 114class BinaryPrintTest(unittest.TestCase): 115 """Tests for utils.binary_print.""" 116 117 @unittest.skip('Causes spurious failures because of side-effects.') 118 def test_string(self): # pylint: disable=no-self-use 119 """Tests that utils.binary_print can print a regular string.""" 120 # Should execute without raising any exceptions. 121 with mock.patch('sys.stdout.buffer.write') as mocked_write: 122 utils.binary_print('hello') 123 mocked_write.assert_called_with('hello\n') 124 125 @unittest.skip('Causes spurious failures because of side-effects.') 126 def test_binary_string(self): # pylint: disable=no-self-use 127 """Tests that utils.binary_print can print a bianry string.""" 128 # Should execute without raising any exceptions. 129 with mock.patch('sys.stdout.buffer.write') as mocked_write: 130 utils.binary_print(b'hello') 131 mocked_write.assert_called_with(b'hello\n') 132 133 134if __name__ == '__main__': 135 unittest.main() 136