1#!/usr/bin/env python 2# -*- coding: utf-8 -*- 3 4# 5# Copyright 2017, Data61 6# Commonwealth Scientific and Industrial Research Organisation (CSIRO) 7# ABN 41 687 119 230. 8# 9# This software may be distributed and modified according to the terms of 10# the BSD 2-Clause license. Note that NO WARRANTY is provided. 11# See "LICENSE_BSD2.txt" for details. 12# 13# @TAG(DATA61_BSD) 14# 15 16from __future__ import absolute_import, division, print_function, \ 17 unicode_literals 18 19import os, shutil, stat, subprocess, sys, tempfile, unittest 20 21ME = os.path.abspath(__file__) 22 23# Make CAmkES importable 24sys.path.append(os.path.join(os.path.dirname(ME), '../../..')) 25 26from camkes.internal.tests.utils import CAmkESTest, cpp_available 27from camkes.parser.stage0 import CPP, parse_makefile_rule 28 29class TestCPP(CAmkESTest): 30 def setUp(self): 31 super(TestCPP, self).setUp() 32 self.reader = CPP() 33 34 @unittest.skipIf(not cpp_available(), 'CPP not found') 35 def test_empty_string(self): 36 content, read = self.reader.parse_string('') 37 38 @unittest.skipIf(not cpp_available(), 'CPP not found') 39 def test_basic_string(self): 40 content, read = self.reader.parse_string('hello world') 41 self.assertIn('hello', content) 42 self.assertIn('world', content) 43 44 @unittest.skipIf(not cpp_available(), 'CPP not found') 45 def test_unicode_string(self): 46 content, read = self.reader.parse_string('���hello world') 47 self.assertIn('���', content) 48 self.assertIn('hello', content) 49 self.assertIn('world', content) 50 51 @unittest.skipIf(not cpp_available(), 'CPP not found') 52 def test_empty_file(self): 53 tmp = self.mkstemp() 54 with open(tmp, 'wt') as f: 55 f.write('hello world') 56 57 content, read = self.reader.parse_file(tmp) 58 59 self.assertIn('hello', content) 60 self.assertIn('world', content) 61 self.assertIn(tmp, read) 62 63 @unittest.skipIf(not cpp_available(), 'CPP not found') 64 def test_non_existent_file(self): 65 # Create a path that we know refers to a file that doesn't exist 66 _, tmp = tempfile.mkstemp() 67 os.remove(tmp) 68 assert not os.path.exists(tmp) 69 70 with self.assertRaises(Exception): 71 self.reader.parse_file(tmp) 72 73 @unittest.skipIf(not cpp_available(), 'CPP not found') 74 def test_include(self): 75 parent = self.mkstemp() 76 child = self.mkstemp() 77 78 with open(child, 'wt') as f: 79 f.write('hello world') 80 81 with open(parent, 'wt') as f: 82 f.write('hello world\n#include "%s"' % child) 83 84 _, read = self.reader.parse_file(parent) 85 86 self.assertIn(parent, read) 87 self.assertIn(child, read) 88 89 @unittest.skipIf(not cpp_available(), 'CPP not found') 90 def test_flags(self): 91 content, _ = self.reader.parse_string('HELLO') 92 self.assertNotIn('world', content) 93 94 parser = CPP(flags=['-DHELLO=world']) 95 content, _ = parser.parse_string('HELLO') 96 97 self.assertIn('world', content) 98 99 # The following tests probe the behaviour of the parse_makefile_rule 100 # function which has been buggy in the past. 101 102 def test_no_cpp_rules(self): 103 ''' 104 Test that an empty list of Makefile rules yields no dependencies. 105 ''' 106 filename = self.mkstemp() 107 108 # Create the file with no content. 109 with open(filename, 'wt') as f: 110 pass 111 112 # Confirm that we get no dependencies out of it. 113 with open(filename) as f: 114 deps = list(parse_makefile_rule(f)) 115 self.assertLen(deps, 0) 116 117 def test_basic_cpp_rule(self): 118 ''' 119 Test that we can correctly handle a basic Makefile rule. 120 ''' 121 filename = self.mkstemp() 122 123 # Create a basic rule. 124 with open(filename, 'wt') as f: 125 f.write('target: a b\n') 126 127 # Confirm we get the correct dependencies. 128 with open(filename) as f: 129 deps = set(parse_makefile_rule(f)) 130 self.assertSetEqual(deps, set(['a', 'b'])) 131 132 def test_split_cpp_rule(self): 133 ''' 134 Test that we can correctly handle rules split over multiple lines. 135 ''' 136 filename = self.mkstemp() 137 138 # Create a split rule. 139 with open(filename, 'wt') as f: 140 f.write('target: a b \\\n' 141 'c \\\n' 142 'd\n') 143 144 # Confirm we get the correct dependencies. 145 with open(filename) as f: 146 deps = set(parse_makefile_rule(f)) 147 self.assertSetEqual(deps, set(['a', 'b', 'c', 'd'])) 148 149 def test_split_cpp_rule2(self): 150 ''' 151 Test a more complicated split rule. 152 ''' 153 filename = self.mkstemp() 154 155 # Create a complicated split rule. 156 with open(filename, 'wt') as f: 157 f.write('target: \\\n' 158 'a b \\\n' 159 '\\\n' 160 'c\n') 161 162 # Confirm we get the correct dependencies. 163 with open(filename) as f: 164 deps = set(parse_makefile_rule(f)) 165 self.assertSetEqual(deps, set(['a', 'b', 'c'])) 166 167 def test_multiple_cpp_rules(self): 168 ''' 169 We should ignore everything after the first Makefile dependency rule. 170 Test that this is actually true. 171 ''' 172 filename = self.mkstemp() 173 174 # Create a file with multiple rules. 175 with open(filename, 'wt') as f: 176 f.write('target: a b c\n' 177 'target2: d e f\n') 178 179 # Confirm we only get the dependencies of the first rule. 180 with open(filename) as f: 181 deps = set(parse_makefile_rule(f)) 182 self.assertSetEqual(deps, set(['a', 'b', 'c'])) 183 184if __name__ == '__main__': 185 unittest.main() 186