divide_and_merge_profiles_test.py revision a8af9a7a2462b00e72deff99327bdb452a715277
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