[autotest] Move dynamic suite code into its own module

No big rewrite, just moving files around

BUG=chromium-os:30266
TEST=unit
TEST=successful run_suite.py run
TEST=suite_enumerator.py, suite_preprocessor.py, and suite_scheduler.py

Change-Id: I2fbcae0332104ce3adcb10a1e90ce94cb209aca8
Reviewed-on: https://gerrit.chromium.org/gerrit/30267
Reviewed-by: Scott Zawalski <scottz@chromium.org>
Commit-Ready: Chris Masone <cmasone@chromium.org>
Tested-by: Chris Masone <cmasone@chromium.org>
diff --git a/server/cros/dynamic_suite/fakes.py b/server/cros/dynamic_suite/fakes.py
new file mode 100644
index 0000000..87df4e2
--- /dev/null
+++ b/server/cros/dynamic_suite/fakes.py
@@ -0,0 +1,89 @@
+# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""Fakes for dynamic_suite-related unit tests."""
+
+import datetime
+from autotest_lib.server.cros.dynamic_suite import job_status
+
+
+class FakeControlData(object):
+    """A fake parsed control file data structure."""
+    def __init__(self, suite, data, expr=False):
+        self.string = 'text-' + data
+        self.name = 'name-' + data
+        self.data = data
+        self.suite = suite
+        self.test_type = 'Client'
+        self.experimental = expr
+        self.dependencies = []
+
+
+class FakeJob(object):
+    """Faked out RPC-client-side Job object."""
+    def __init__(self, id=0, statuses=[], hostnames=[]):
+        self.id = id
+        self.hostnames = hostnames if hostnames else ['host%d' % id]
+        self.owner = 'tester'
+        self.name = 'Fake Job %d' % self.id
+        self.statuses = statuses
+
+
+class FakeHost(object):
+    """Faked out RPC-client-side Host object."""
+    def __init__(self, hostname='', status='Ready'):
+        self.hostname = hostname
+        self.status = status
+
+
+class FakeLabel(object):
+    """Faked out RPC-client-side Label object."""
+    def __init__(self, id=0):
+        self.id = id
+
+
+class FakeStatus(object):
+    """Fake replacement for server-side job status objects.
+
+    @var status: 'GOOD', 'FAIL', 'ERROR', etc.
+    @var test_name: name of the test this is status for
+    @var reason: reason for failure, if any
+    @var aborted: present and True if the job was aborted.  Optional.
+    """
+    def __init__(self, code, name, reason, aborted=None, hostname=None):
+        self.status = code
+        self.test_name = name
+        self.reason = reason
+        self.hostname = hostname if hostname else 'hostless'
+        self.entry = {}
+        self.test_started_time = '2012-11-11 11:11:11'
+        self.test_finished_time = '2012-11-11 12:12:12'
+        if aborted:
+            self.entry['aborted'] = True
+        if hostname:
+            self.entry['host'] = {'hostname': hostname}
+
+
+    def __repr__(self):
+        return '%s\t%s\t%s: %s' % (self.status, self.test_name, self.reason,
+                                   self.hostname)
+
+
+    def equals_record(self, status):
+        """Compares this object to a recorded status."""
+        if 'aborted' in self.entry and self.entry['aborted']:
+            return status._status == 'ABORT'
+        return (self.status == status._status and
+                status._test_name.endswith(self.test_name) and
+                self.reason == status._reason)
+
+
+    def equals_hostname_record(self, status):
+        """Compares this object to a recorded status.
+
+        Expects the test name field of |status| to contain |self.hostname|.
+        """
+        return (self.status == status._status and
+                self.hostname in status._test_name and
+                self.reason == status._reason)