1import subprocess 2import sys 3import re 4 5try: 6 # Make terminal colors work on windows 7 import colorama 8 colorama.init() 9except ImportError: 10 pass 11 12def add_nanopb_builders(env): 13 '''Add the necessary builder commands for nanopb tests.''' 14 15 # Build command that runs a test program and saves the output 16 def run_test(target, source, env): 17 if len(source) > 1: 18 infile = open(str(source[1])) 19 else: 20 infile = None 21 22 if env.has_key("COMMAND"): 23 args = [env["COMMAND"]] 24 else: 25 args = [str(source[0])] 26 27 if env.has_key('ARGS'): 28 args.extend(env['ARGS']) 29 30 print('Command line: ' + str(args)) 31 pipe = subprocess.Popen(args, 32 stdin = infile, 33 stdout = open(str(target[0]), 'w'), 34 stderr = sys.stderr) 35 result = pipe.wait() 36 if result == 0: 37 print('\033[32m[ OK ]\033[0m Ran ' + args[0]) 38 else: 39 print('\033[31m[FAIL]\033[0m Program ' + args[0] + ' returned ' + str(result)) 40 return result 41 42 run_test_builder = Builder(action = run_test, 43 suffix = '.output') 44 env.Append(BUILDERS = {'RunTest': run_test_builder}) 45 46 # Build command that decodes a message using protoc 47 def decode_actions(source, target, env, for_signature): 48 esc = env['ESCAPE'] 49 dirs = ' '.join(['-I' + esc(env.GetBuildPath(d)) for d in env['PROTOCPATH']]) 50 return '$PROTOC $PROTOCFLAGS %s --decode=%s %s <%s >%s' % ( 51 dirs, env['MESSAGE'], esc(str(source[1])), esc(str(source[0])), esc(str(target[0]))) 52 53 decode_builder = Builder(generator = decode_actions, 54 suffix = '.decoded') 55 env.Append(BUILDERS = {'Decode': decode_builder}) 56 57 # Build command that encodes a message using protoc 58 def encode_actions(source, target, env, for_signature): 59 esc = env['ESCAPE'] 60 dirs = ' '.join(['-I' + esc(env.GetBuildPath(d)) for d in env['PROTOCPATH']]) 61 return '$PROTOC $PROTOCFLAGS %s --encode=%s %s <%s >%s' % ( 62 dirs, env['MESSAGE'], esc(str(source[1])), esc(str(source[0])), esc(str(target[0]))) 63 64 encode_builder = Builder(generator = encode_actions, 65 suffix = '.encoded') 66 env.Append(BUILDERS = {'Encode': encode_builder}) 67 68 # Build command that asserts that two files be equal 69 def compare_files(target, source, env): 70 data1 = open(str(source[0]), 'rb').read() 71 data2 = open(str(source[1]), 'rb').read() 72 if data1 == data2: 73 print('\033[32m[ OK ]\033[0m Files equal: ' + str(source[0]) + ' and ' + str(source[1])) 74 return 0 75 else: 76 print('\033[31m[FAIL]\033[0m Files differ: ' + str(source[0]) + ' and ' + str(source[1])) 77 return 1 78 79 compare_builder = Builder(action = compare_files, 80 suffix = '.equal') 81 env.Append(BUILDERS = {'Compare': compare_builder}) 82 83 # Build command that checks that each pattern in source2 is found in source1. 84 def match_files(target, source, env): 85 data = open(str(source[0]), 'rU').read() 86 patterns = open(str(source[1])) 87 for pattern in patterns: 88 if pattern.strip(): 89 invert = False 90 if pattern.startswith('! '): 91 invert = True 92 pattern = pattern[2:] 93 94 status = re.search(pattern.strip(), data, re.MULTILINE) 95 96 if not status and not invert: 97 print('\033[31m[FAIL]\033[0m Pattern not found in ' + str(source[0]) + ': ' + pattern) 98 return 1 99 elif status and invert: 100 print('\033[31m[FAIL]\033[0m Pattern should not exist, but does in ' + str(source[0]) + ': ' + pattern) 101 return 1 102 else: 103 print('\033[32m[ OK ]\033[0m All patterns found in ' + str(source[0])) 104 return 0 105 106 match_builder = Builder(action = match_files, suffix = '.matched') 107 env.Append(BUILDERS = {'Match': match_builder}) 108 109 110