#!/usr/bin/python # # Copyright 2010 Google Inc. All Rights Reserved. __author__ = 'asharif@google.com (Ahmad Sharif)' import os import random import shutil import tempfile import unittest from cros_utils import command_executer from cros_utils import misc class DivideAndMergeProfilesTest(unittest.TestCase): def tearDown(self): shutil.rmtree(self._program_dir) for profile_dir in self._profile_dirs: shutil.rmtree(profile_dir) def setUp(self): self._ce = command_executer.GetCommandExecuter() self._program_dir = tempfile.mkdtemp() self._writeProgram() self._writeMakefile() with misc.WorkingDirectory(self._program_dir): self._ce.RunCommand('make') num_profile_dirs = 2 self._profile_dirs = [] for i in range(num_profile_dirs): profile_dir = tempfile.mkdtemp() command = ('GCOV_PREFIX_STRIP=%s GCOV_PREFIX=$(/bin/pwd) ' ' %s/program' % (profile_dir.count('/'), self._program_dir)) with misc.WorkingDirectory(profile_dir): self._ce.RunCommand(command) self._profile_dirs.append(profile_dir) self._merge_program = '/home/build/static/projects/crosstool/profile-merge/v14.5/profile_merge.par' def _writeMakefile(self): makefile_contents = """ CC = gcc CFLAGS = -fprofile-generate SRCS=$(wildcard *.c) OBJS=$(SRCS:.c=.o) all: program program: $(OBJS) $(CC) -o $@ $^ $(CFLAGS) %.o: %.c $(CC) -c -o $@ $^ $(CFLAGS)""" makefile = os.path.join(self._program_dir, 'Makefile') with open(makefile, 'w') as f: print >> f, makefile_contents def _writeProgram(self, num_files=100): for i in range(num_files): current_file = os.path.join(self._program_dir, '%s.c' % i) with open(current_file, 'w') as f: if i != num_files - 1: print >> f, 'extern void foo%s();' % (i + 1) print >> f, 'void foo%s(){foo%s();}' % (i, i + 1) else: print >> f, "void foo%s(){printf(\"\");}" % i if i == 0: print >> f, 'int main(){foo%s(); return 0;}' % i def testMerge(self): reference_output = self._getReferenceOutput() my_output = self._getMyOutput() ret = self._diffOutputs(reference_output, my_output) shutil.rmtree(my_output) shutil.rmtree(reference_output) self.assertTrue(ret == 0) def _diffOutputs(self, reference, mine): command = 'diff -uNr %s %s' % (reference, mine) return self._ce.RunCommand(command) def _getMyOutput(self, args=''): my_output = tempfile.mkdtemp() my_merge_program = os.path.join( os.path.dirname(__file__), 'divide_and_merge_profiles.py') command = ('python %s --inputs=%s --output=%s ' '--chunk_size=10 ' '--merge_program=%s ' '%s' % (my_merge_program, ','.join(self._profile_dirs), my_output, self._merge_program, args)) self._ce.RunCommand(command) return my_output def _getReferenceOutput(self, args=''): # First do a regular merge. reference_output = tempfile.mkdtemp() command = ('%s --inputs=%s --output=%s %s' % (self._merge_program, ','.join(self._profile_dirs), reference_output, args)) self._ce.RunCommand(command) return reference_output def testMergeWithMultipliers(self): num_profiles = len(self._profile_dirs) multipliers = [str(random.randint(0, num_profiles)) \ for _ in range(num_profiles)] args = '--multipliers=%s' % ','.join(multipliers) reference_output = self._getReferenceOutput(args) my_output = self._getMyOutput(args) ret = self._diffOutputs(reference_output, my_output) shutil.rmtree(my_output) shutil.rmtree(reference_output) self.assertTrue(ret == 0) if __name__ == '__main__': unittest.main()