1#!/usr/bin/python 2# 3# Copyright 2010 Google Inc. All Rights Reserved. 4 5__author__ = 'asharif@google.com (Ahmad Sharif)' 6 7import os 8import random 9import shutil 10import tempfile 11import unittest 12 13from cros_utils import command_executer 14from cros_utils import misc 15 16 17class DivideAndMergeProfilesTest(unittest.TestCase): 18 19 def tearDown(self): 20 shutil.rmtree(self._program_dir) 21 for profile_dir in self._profile_dirs: 22 shutil.rmtree(profile_dir) 23 24 def setUp(self): 25 self._ce = command_executer.GetCommandExecuter() 26 self._program_dir = tempfile.mkdtemp() 27 self._writeProgram() 28 self._writeMakefile() 29 with misc.WorkingDirectory(self._program_dir): 30 self._ce.RunCommand('make') 31 num_profile_dirs = 2 32 self._profile_dirs = [] 33 for i in range(num_profile_dirs): 34 profile_dir = tempfile.mkdtemp() 35 command = ('GCOV_PREFIX_STRIP=%s GCOV_PREFIX=$(/bin/pwd) ' 36 ' %s/program' % (profile_dir.count('/'), self._program_dir)) 37 with misc.WorkingDirectory(profile_dir): 38 self._ce.RunCommand(command) 39 self._profile_dirs.append(profile_dir) 40 self._merge_program = '/home/build/static/projects/crosstool/profile-merge/v14.5/profile_merge.par' 41 42 def _writeMakefile(self): 43 makefile_contents = """ 44CC = gcc 45 46CFLAGS = -fprofile-generate 47 48SRCS=$(wildcard *.c) 49 50OBJS=$(SRCS:.c=.o) 51 52all: program 53 54program: $(OBJS) 55 $(CC) -o $@ $^ $(CFLAGS) 56 57%.o: %.c 58 $(CC) -c -o $@ $^ $(CFLAGS)""" 59 60 makefile = os.path.join(self._program_dir, 'Makefile') 61 with open(makefile, 'w') as f: 62 print >> f, makefile_contents 63 64 def _writeProgram(self, num_files=100): 65 for i in range(num_files): 66 current_file = os.path.join(self._program_dir, '%s.c' % i) 67 with open(current_file, 'w') as f: 68 if i != num_files - 1: 69 print >> f, 'extern void foo%s();' % (i + 1) 70 print >> f, 'void foo%s(){foo%s();}' % (i, i + 1) 71 else: 72 print >> f, "void foo%s(){printf(\"\");}" % i 73 if i == 0: 74 print >> f, 'int main(){foo%s(); return 0;}' % i 75 76 def testMerge(self): 77 reference_output = self._getReferenceOutput() 78 my_output = self._getMyOutput() 79 80 ret = self._diffOutputs(reference_output, my_output) 81 shutil.rmtree(my_output) 82 shutil.rmtree(reference_output) 83 self.assertTrue(ret == 0) 84 85 def _diffOutputs(self, reference, mine): 86 command = 'diff -uNr %s %s' % (reference, mine) 87 return self._ce.RunCommand(command) 88 89 def _getMyOutput(self, args=''): 90 my_output = tempfile.mkdtemp() 91 my_merge_program = os.path.join( 92 os.path.dirname(__file__), 'divide_and_merge_profiles.py') 93 command = ('python %s --inputs=%s --output=%s ' 94 '--chunk_size=10 ' 95 '--merge_program=%s ' 96 '%s' % (my_merge_program, ','.join(self._profile_dirs), 97 my_output, self._merge_program, args)) 98 self._ce.RunCommand(command) 99 return my_output 100 101 def _getReferenceOutput(self, args=''): 102 # First do a regular merge. 103 reference_output = tempfile.mkdtemp() 104 command = ('%s --inputs=%s --output=%s %s' % 105 (self._merge_program, ','.join(self._profile_dirs), 106 reference_output, args)) 107 self._ce.RunCommand(command) 108 return reference_output 109 110 def testMergeWithMultipliers(self): 111 num_profiles = len(self._profile_dirs) 112 multipliers = [str(random.randint(0, num_profiles)) \ 113 for _ in range(num_profiles)] 114 args = '--multipliers=%s' % ','.join(multipliers) 115 116 reference_output = self._getReferenceOutput(args) 117 my_output = self._getMyOutput(args) 118 119 ret = self._diffOutputs(reference_output, my_output) 120 121 shutil.rmtree(my_output) 122 shutil.rmtree(reference_output) 123 self.assertTrue(ret == 0) 124 125 126if __name__ == '__main__': 127 unittest.main() 128