Added the base Generation base class.

Algorithm specific subclasses, e.g., Genetic Algorithm and Hill Climbing,
should extend this base class.

BUG=None
TEST=unit testing for the pipeline stage, pipeline workers and generation.

Change-Id: Icc79b02099521db74fed7c1017691e2a8719be23
Reviewed-on: https://gerrit-int.chromium.org/41081
Reviewed-by: Luis Lozano <llozano@chromium.org>
Reviewed-by: Simon Que <sque@google.com>
Tested-by: Yuheng Long <yuhenglong@google.com>
Commit-Queue: Yuheng Long <yuhenglong@google.com>
diff --git a/bestflags/generation_test.py b/bestflags/generation_test.py
index b977925..a8bdf59 100644
--- a/bestflags/generation_test.py
+++ b/bestflags/generation_test.py
@@ -5,40 +5,83 @@
 
 __author__ = 'yuhenglong@google.com (Yuheng Long)'
 
+import random
 import unittest
 
-import generation
+from generation import Generation
+from mock_task import MockTask
+
+
+# Pick an integer at random.
+TESTSTAGE = -125
+
+# The number of tasks to be put in a generation to be tested.
+NUMTASKS = 20
+
+# The stride of permutation used to shuffle the input list of tasks. Should be
+# relatively prime with NUMTASKS.
+STRIDE = 7
+
+
+class GenerationMockTask(MockTask):
+  """This class defines the mock task to test the Generation class.
+
+  The task instances will be inserted into a set. Therefore the hash and the
+  equal methods are overridden. The generation class considers the identifier to
+  set the cost of the task in a set, thus the identifier is used in the
+  overriding methods.
+  """
+
+  def __hash__(self):
+    return self._identifier
+
+  def __eq__(self, other):
+    if isinstance(other, MockTask):
+      return self._identifier == other.GetIdentifier(self._stage)
+    return False
 
 
 class GenerationTest(unittest.TestCase):
   """This class test the Generation class.
 
-  A generation class should not produce a task that has been generated before.
-  The task returned as the best task should really be the best.
-
-  Given two generations, if the second one has improved upon the first one,
-  the result method should return true and false otherwise.
+  Given a set of tasks in the generation, if there is any task that is pending,
+  then the Done method will return false, and true otherwise.
   """
 
-  def setUp(self):
-    pass
+  def testDone(self):
+    """"Test the Done method.
 
-  def testNext(self):
-    """"Test the next method.
-
-    Call the next method n times and all the tasks in each generation should be
-    unique.
-    """
-    pass
-
-  def testImprove(self):
-    """"Test the improve method.
-
-    If the successor generation has improvement upon the parent generation, the
-    result from the improve method should indicate so.
+    Produce a generation with a set of tasks. Set the cost of the task one by
+    one and verify that the Done method returns false before setting the cost
+    for all the tasks. After the costs of all the tasks are set, the Done method
+    should return true.
     """
 
-    pass
+    random.seed(0)
+
+    testing_tasks = range(NUMTASKS)
+
+    # The tasks for the generation to be tested.
+    generation_tasks = [GenerationMockTask(TESTSTAGE, t) for t in testing_tasks]
+
+    gen = Generation(set(generation_tasks), None)
+
+    # Permute the list.
+    permutation = [(t * STRIDE) % NUMTASKS for t in range(NUMTASKS)]
+    permuted_tasks = [testing_tasks[index] for index in permutation]
+
+    # The Done method of the Generation should return false before all the tasks
+    # in the permuted list are set.
+    for testing_task in permuted_tasks:
+      assert not gen.Done()
+
+      # Mark a task as done by calling the UpdateTask method of the generation.
+      # Send the generation the task as well as its results.
+      gen.UpdateTask(GenerationMockTask(TESTSTAGE, testing_task))
+
+    # The Done method should return true after all the tasks in the permuted
+    # list is set.
+    assert gen.Done()
 
 if __name__ == '__main__':
   unittest.main()