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