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