Yuheng Long | 16d7a52 | 2013-07-19 16:29:13 -0700 | [diff] [blame] | 1 | # Copyright (c) 2013 The Chromium OS Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
Yuheng Long | 49358b7 | 2013-07-10 14:45:29 -0700 | [diff] [blame] | 5 | """Task unittest. |
| 6 | |
| 7 | Part of the Chrome build flags optimization. |
| 8 | """ |
Yuheng Long | f20cffa | 2013-06-03 18:46:00 -0700 | [diff] [blame] | 9 | |
| 10 | __author__ = 'yuhenglong@google.com (Yuheng Long)' |
| 11 | |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 12 | import random |
| 13 | import sys |
Yuheng Long | f20cffa | 2013-06-03 18:46:00 -0700 | [diff] [blame] | 14 | import unittest |
| 15 | |
| 16 | import task |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 17 | from task import Task |
| 18 | |
| 19 | # The number of flags be tested. |
| 20 | NUM_FLAGS = 20 |
| 21 | |
| 22 | # The random build result values used to test get set result method. |
| 23 | RANDOM_BUILD_RESULT = 100 |
| 24 | |
| 25 | # The random test result values used to test get set result method. |
| 26 | RANDOM_TESTRESULT = 100 |
| 27 | |
| 28 | |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 29 | class MockFlagSet(object): |
| 30 | """This class emulates a set of flags. |
| 31 | |
| 32 | It returns the flags and hash value, when the FormattedForUse method and the |
| 33 | __hash__ method is called, respectively. These values are initialized when the |
| 34 | MockFlagSet instance is constructed. |
| 35 | """ |
| 36 | |
| 37 | def __init__(self, flags=0, hash_value=-1): |
| 38 | self._flags = flags |
| 39 | self._hash_value = hash_value |
| 40 | |
| 41 | def __eq__(self, other): |
| 42 | assert isinstance(other, MockFlagSet) |
| 43 | return self._flags == other.FormattedForUse() |
| 44 | |
| 45 | def FormattedForUse(self): |
| 46 | return self._flags |
| 47 | |
| 48 | def __hash__(self): |
| 49 | return self._hash_value |
| 50 | |
| 51 | def GetHash(self): |
| 52 | return self._hash_value |
Yuheng Long | f20cffa | 2013-06-03 18:46:00 -0700 | [diff] [blame] | 53 | |
| 54 | |
| 55 | class TaskTest(unittest.TestCase): |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 56 | """This class test the Task class.""" |
Yuheng Long | f20cffa | 2013-06-03 18:46:00 -0700 | [diff] [blame] | 57 | |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 58 | def testEqual(self): |
| 59 | """Test the equal method of the task. |
Yuheng Long | f20cffa | 2013-06-03 18:46:00 -0700 | [diff] [blame] | 60 | |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 61 | Two tasks are equal if and only if their encapsulated flag_sets are equal. |
| 62 | """ |
Yuheng Long | f20cffa | 2013-06-03 18:46:00 -0700 | [diff] [blame] | 63 | |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 64 | flags = range(NUM_FLAGS) |
Yuheng Long | f20cffa | 2013-06-03 18:46:00 -0700 | [diff] [blame] | 65 | |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 66 | # Two tasks having the same flag set should be equivalent. |
| 67 | flag_sets = [MockFlagSet(flag) for flag in flags] |
| 68 | for flag_set in flag_sets: |
Yuheng Long | ccfaf2f | 2013-08-02 14:27:45 -0700 | [diff] [blame] | 69 | assert Task(flag_set) == Task(flag_set) |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 70 | |
| 71 | # Two tasks having different flag set should be different. |
| 72 | for flag_set in flag_sets: |
Yuheng Long | ccfaf2f | 2013-08-02 14:27:45 -0700 | [diff] [blame] | 73 | test_task = Task(flag_set) |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 74 | other_flag_sets = [flags for flags in flag_sets if flags != flag_set] |
| 75 | for flag_set1 in other_flag_sets: |
Yuheng Long | ccfaf2f | 2013-08-02 14:27:45 -0700 | [diff] [blame] | 76 | assert test_task != Task(flag_set1) |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 77 | |
| 78 | def testHash(self): |
| 79 | """Test the hash method of the task. |
| 80 | |
| 81 | Two tasks are equal if and only if their encapsulated flag_sets are equal. |
| 82 | """ |
| 83 | |
| 84 | # Random identifier that is not relevant in this test. |
| 85 | identifier = random.randint(-sys.maxint - 1, -1) |
| 86 | |
| 87 | flag_sets = [MockFlagSet(identifier, value) for value in range(NUM_FLAGS)] |
| 88 | for flag_set in flag_sets: |
| 89 | # The hash of a task is the same as the hash of its flag set. |
Yuheng Long | ccfaf2f | 2013-08-02 14:27:45 -0700 | [diff] [blame] | 90 | hash_task = Task(flag_set) |
| 91 | hash_value = hash(hash_task) |
| 92 | assert hash_value == flag_set.GetHash() |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 93 | |
| 94 | # The hash of a task does not change. |
Yuheng Long | ccfaf2f | 2013-08-02 14:27:45 -0700 | [diff] [blame] | 95 | assert hash_value == hash(hash_task) |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 96 | |
| 97 | def testGetIdentifier(self): |
| 98 | """Test the get identifier method of the task. |
| 99 | |
| 100 | The get identifier method should returns the flag set in the build stage. |
| 101 | """ |
| 102 | |
| 103 | flag_sets = [MockFlagSet(flag) for flag in range(NUM_FLAGS)] |
| 104 | for flag_set in flag_sets: |
Yuheng Long | ccfaf2f | 2013-08-02 14:27:45 -0700 | [diff] [blame] | 105 | identifier_task = Task(flag_set) |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 106 | |
| 107 | identifier = identifier_task.GetIdentifier(task.BUILD_STAGE) |
| 108 | |
| 109 | # The task formats the flag set into a string. |
| 110 | assert identifier == str(flag_set.FormattedForUse()) |
| 111 | |
| 112 | def testGetSetResult(self): |
| 113 | """Test the get and set result methods of the task. |
| 114 | |
| 115 | The get result method should return the same results as were set. |
| 116 | """ |
| 117 | |
| 118 | flag_sets = [MockFlagSet(flag) for flag in range(NUM_FLAGS)] |
| 119 | for flag_set in flag_sets: |
Yuheng Long | ccfaf2f | 2013-08-02 14:27:45 -0700 | [diff] [blame] | 120 | result_task = Task(flag_set) |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 121 | |
| 122 | # The get result method should return the same results as were set, in |
| 123 | # build stage. Currently, the build result is a 5-element tuple containing |
| 124 | # the checksum of the result image, the performance cost of the build, the |
| 125 | # compilation image, the length of the build, and the length of the text |
| 126 | # section of the build. |
| 127 | result = tuple([random.randint(0, RANDOM_BUILD_RESULT) for _ in range(5)]) |
| 128 | result_task.SetResult(task.BUILD_STAGE, result) |
| 129 | assert result == result_task.GetResult(task.BUILD_STAGE) |
| 130 | |
| 131 | # The checksum is the identifier of the test stage. |
| 132 | identifier = result_task.GetIdentifier(task.TEST_STAGE) |
| 133 | # The first element of the result tuple is the checksum. |
| 134 | assert identifier == result[0] |
| 135 | |
| 136 | # The get result method should return the same results as were set, in |
| 137 | # test stage. |
| 138 | random_test_result = random.randint(0, RANDOM_TESTRESULT) |
| 139 | result_task.SetResult(task.TEST_STAGE, random_test_result) |
| 140 | test_result = result_task.GetResult(task.TEST_STAGE) |
| 141 | assert test_result == random_test_result |
| 142 | |
| 143 | def testDone(self): |
| 144 | """Test the done methods of the task. |
| 145 | |
| 146 | The done method should return false is the task has not perform and return |
| 147 | true after the task is finished. |
| 148 | """ |
| 149 | |
| 150 | flags = range(NUM_FLAGS) |
| 151 | |
| 152 | flag_sets = [MockFlagSet(flag) for flag in flags] |
| 153 | for flag_set in flag_sets: |
Yuheng Long | ccfaf2f | 2013-08-02 14:27:45 -0700 | [diff] [blame] | 154 | work_task = Task(flag_set) |
Yuheng Long | b15d41c | 2013-07-25 10:02:36 -0700 | [diff] [blame] | 155 | |
| 156 | # The task has not been compiled nor tested. |
| 157 | assert not work_task.Done(task.TEST_STAGE) |
| 158 | assert not work_task.Done(task.BUILD_STAGE) |
| 159 | |
| 160 | # After the task has been compiled, it should indicate finished in BUILD |
| 161 | # stage. |
| 162 | result = tuple([random.randint(0, RANDOM_BUILD_RESULT) for _ in range(5)]) |
| 163 | work_task.SetResult(task.BUILD_STAGE, result) |
| 164 | assert not work_task.Done(task.TEST_STAGE) |
| 165 | assert work_task.Done(task.BUILD_STAGE) |
| 166 | |
| 167 | # After the task has been tested, it should indicate finished in TEST |
| 168 | # stage. |
| 169 | work_task.SetResult(task.TEST_STAGE, random.randint(0, RANDOM_TESTRESULT)) |
| 170 | assert work_task.Done(task.TEST_STAGE) |
| 171 | assert work_task.Done(task.BUILD_STAGE) |
Yuheng Long | f20cffa | 2013-06-03 18:46:00 -0700 | [diff] [blame] | 172 | |
| 173 | if __name__ == '__main__': |
| 174 | unittest.main() |