| #!/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() |