divide_and_merge_profiles_test.py revision f81680c018729fd4499e1e200d04b48c4b90127c
1#!/usr/bin/python2.6 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 utils import command_executer 14from utils import misc 15 16 17class DivideAndMergeProfilesTest(unittest.TestCase): 18 def tearDown(self): 19 shutil.rmtree(self._program_dir) 20 for profile_dir in self._profile_dirs: 21 shutil.rmtree(profile_dir) 22 23 def setUp(self): 24 self._ce = command_executer.GetCommandExecuter() 25 self._program_dir = tempfile.mkdtemp() 26 self._writeProgram() 27 self._writeMakefile() 28 with misc.WorkingDirectory(self._program_dir): 29 self._ce.RunCommand("make") 30 num_profile_dirs = 2 31 self._profile_dirs = [] 32 for i in range(num_profile_dirs): 33 profile_dir = tempfile.mkdtemp() 34 command = ("GCOV_PREFIX_STRIP=%s GCOV_PREFIX=$(/bin/pwd) " 35 " %s/program" % 36 (profile_dir.count("/"), 37 self._program_dir)) 38 with misc.WorkingDirectory(profile_dir): 39 self._ce.RunCommand(command) 40 self._profile_dirs.append(profile_dir) 41 self._merge_program = "/home/build/static/projects/crosstool/profile-merge/v14.5/profile_merge.par" 42 43 def _writeMakefile(self): 44 makefile_contents = """ 45CC = gcc 46 47CFLAGS = -fprofile-generate 48 49SRCS=$(wildcard *.c) 50 51OBJS=$(SRCS:.c=.o) 52 53all: program 54 55program: $(OBJS) 56 $(CC) -o $@ $^ $(CFLAGS) 57 58%.o: %.c 59 $(CC) -c -o $@ $^ $(CFLAGS)""" 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(os.path.dirname(__file__), 92 "divide_and_merge_profiles.py") 93 command = ("python %s --inputs=%s --output=%s " 94 "--chunk_size=10 " 95 "--merge_program=%s " 96 "%s" % 97 (my_merge_program, 98 ",".join(self._profile_dirs), 99 my_output, 100 self._merge_program, 101 args)) 102 self._ce.RunCommand(command) 103 return my_output 104 105 def _getReferenceOutput(self, args=""): 106 # First do a regular merge. 107 reference_output = tempfile.mkdtemp() 108 command = ("%s --inputs=%s --output=%s %s" % 109 (self._merge_program, 110 ",".join(self._profile_dirs), 111 reference_output, 112 args)) 113 self._ce.RunCommand(command) 114 return reference_output 115 116 def testMergeWithMultipliers(self): 117 num_profiles = len(self._profile_dirs) 118 multipliers = [str(random.randint(0, num_profiles)) \ 119 for _ in range(num_profiles)] 120 args = "--multipliers=%s" % ",".join(multipliers) 121 122 reference_output = self._getReferenceOutput(args) 123 my_output = self._getMyOutput(args) 124 125 ret = self._diffOutputs(reference_output, my_output) 126 127 shutil.rmtree(my_output) 128 shutil.rmtree(reference_output) 129 self.assertTrue(ret == 0) 130 131if __name__ == "__main__": 132 unittest.main() 133