gs_offloader_unittest.py revision 80dfb1e9366b74f6c5a928e33793012e5a8ebc5a
197d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang# Copyright 2016 The Chromium OS Authors. All rights reserved.
2ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# Use of this source code is governed by a BSD-style license that can be
3ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# found in the LICENSE file.
4ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
55ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddowimport __builtin__
6ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport Queue
797d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tangimport base64
8ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport datetime
9ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport logging
10ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport os
11ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport shutil
122e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnetteimport signal
13ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport sys
14ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport tempfile
15ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport time
16ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport unittest
17ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
18ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport mox
19ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
20ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport common
21328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tangfrom autotest_lib.client.common_lib import global_config, site_utils
221b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shifrom autotest_lib.client.common_lib import time_utils
231b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shifrom autotest_lib.client.common_lib import utils
24ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnettefrom autotest_lib.scheduler import email_manager
25beb9e01b8aebdd33b7c866fbdfef64bc77f139e5Prathmesh Prabhufrom autotest_lib.site_utils import gs_offloader
26beb9e01b8aebdd33b7c866fbdfef64bc77f139e5Prathmesh Prabhufrom autotest_lib.site_utils import job_directories
272d981eee42e4f9fb4f6d726b97aa8122322543beNingning Xiafrom autotest_lib.tko import models
2824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
29ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# Test value to use for `days_old`, if nothing else is required.
30ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette_TEST_EXPIRATION_AGE = 7
31ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
32ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# When constructing sample time values for testing expiration,
33ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# allow this many seconds between the expiration time and the
34ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# current time.
35ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette_MARGIN_SECS = 10.0
36ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
37ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
38ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnettedef _get_options(argv):
39ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Helper function to exercise command line parsing.
40ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
41ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    @param argv Value of sys.argv to be parsed.
42ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
43ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
44ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    sys.argv = ['bogus.py'] + argv
45ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    return gs_offloader.parse_options()
46ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
47ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
48dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basiclass OffloaderOptionsTests(mox.MoxTestBase):
49ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    """Tests for the `Offloader` constructor.
50ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette
51ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    Tests that offloader instance fields are set as expected
52ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    for given command line options.
53ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette
54ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    """
55ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette
56ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    _REGULAR_ONLY = set([job_directories.RegularJobDirectory])
57ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    _SPECIAL_ONLY = set([job_directories.SpecialJobDirectory])
58ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    _BOTH = _REGULAR_ONLY | _SPECIAL_ONLY
59ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
6024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
61dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi    def setUp(self):
62dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        super(OffloaderOptionsTests, self).setUp()
63dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.mox.StubOutWithMock(utils, 'get_offload_gsuri')
64f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        gs_offloader.GS_OFFLOADING_ENABLED = True
650df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        gs_offloader.GS_OFFLOADER_MULTIPROCESSING = False
66dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi
6724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6897d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang    def _mock_get_offload_func(self, is_moblab, multiprocessing=False,
695ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                               pubsub_topic=None, delete_age=0):
70dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        """Mock the process of getting the offload_dir function."""
71dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        if is_moblab:
72dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi            expected_gsuri = '%sresults/%s/%s/' % (
73dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                    global_config.global_config.get_config_value(
74dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                            'CROS', 'image_storage_server'),
75dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                    'Fa:ke:ma:c0:12:34', 'rand0m-uu1d')
76dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        else:
77dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi            expected_gsuri = utils.DEFAULT_OFFLOAD_GSURI
78dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        utils.get_offload_gsuri().AndReturn(expected_gsuri)
795ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        offload_func = gs_offloader.get_offload_dir_func(expected_gsuri,
805ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow            multiprocessing, delete_age, pubsub_topic)
81dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.mox.StubOutWithMock(gs_offloader, 'get_offload_dir_func')
8297d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        gs_offloader.get_offload_dir_func(expected_gsuri, multiprocessing,
835ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow            delete_age, pubsub_topic).AndReturn(offload_func)
84dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.mox.ReplayAll()
85dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        return offload_func
86dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi
8724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
88ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_process_no_options(self):
89ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test default offloader options."""
90dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(False)
91ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(_get_options([]))
92ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
93ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
94ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
95ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
96dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
975ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
985ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
99ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
10024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
101ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_process_all_option(self):
102ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --all option."""
103dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(False)
104ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(_get_options(['--all']))
105ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes), self._BOTH)
106ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
107ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
108dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
1095ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1105ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
111ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
11224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
113ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_process_hosts_option(self):
114ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --hosts option."""
115dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(False)
116ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
117ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--hosts']))
118ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
119ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._SPECIAL_ONLY)
120ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
121ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
122dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
1235ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1245ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
125ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
12624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
127ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_parallelism_option(self):
128ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --parallelism option."""
129dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(False)
130ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
131ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--parallelism', '2']))
132ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
133ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
134ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 2)
135ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
136dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
1375ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1385ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
139ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
14024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
141ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_delete_only_option(self):
142ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --delete_only option."""
143ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
144ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--delete_only']))
145ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
146ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
147ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
148ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
149ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         gs_offloader.delete_files)
1505ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1515ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
15297d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.assertIsNone(offloader._pubsub_topic)
153ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
15424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
155df4751eaab3405bc4f564d033681d093958f0c10Simran Basi    def test_days_old_option(self):
156ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --days_old option."""
1575ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        offload_func = self._mock_get_offload_func(False, delete_age=7)
158ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
159ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--days_old', '7']))
160ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
161ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
162ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
163ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
164dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
1655ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 7)
1665ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 7)
167ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
16824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
169dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi    def test_moblab_gsuri_generation(self):
170dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        """Test offloader construction for Moblab."""
171dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(True)
172dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offloader = gs_offloader.Offloader(_get_options([]))
173dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.assertEqual(set(offloader._jobdir_classes),
174dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         self._REGULAR_ONLY)
175dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.assertEqual(offloader._processes, 1)
176dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.assertEqual(offloader._offload_func,
177dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
1785ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1795ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
180dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi
181ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
182f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi    def test_globalconfig_offloading_flag(self):
183f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        """Test enabling of --delete_only via global_config."""
184f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        gs_offloader.GS_OFFLOADING_ENABLED = False
185f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        offloader = gs_offloader.Offloader(
186f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi                _get_options([]))
187f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        self.assertEqual(offloader._offload_func,
188f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi                         gs_offloader.delete_files)
189f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi
1900df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang    def test_offloader_multiprocessing_flag_set(self):
1910df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        """Test multiprocessing is set."""
1920df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offload_func = self._mock_get_offload_func(True, True)
1930df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offloader = gs_offloader.Offloader(_get_options(['-m']))
1940df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.assertEqual(offloader._offload_func,
1950df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang                         offload_func)
1960df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.mox.VerifyAll()
1970df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang
1980df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang    def test_offloader_multiprocessing_flag_not_set_default_false(self):
1990df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        """Test multiprocessing is set."""
2000df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        gs_offloader.GS_OFFLOADER_MULTIPROCESSING = False
2010df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offload_func = self._mock_get_offload_func(True, False)
2020df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offloader = gs_offloader.Offloader(_get_options([]))
2030df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.assertEqual(offloader._offload_func,
2040df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang                         offload_func)
2050df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.mox.VerifyAll()
2060df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang
2070df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang    def test_offloader_multiprocessing_flag_not_set_default_true(self):
2080df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        """Test multiprocessing is set."""
2090df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        gs_offloader.GS_OFFLOADER_MULTIPROCESSING = True
2100df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offload_func = self._mock_get_offload_func(True, True)
2110df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offloader = gs_offloader.Offloader(_get_options([]))
2120df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.assertEqual(offloader._offload_func,
2130df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang                         offload_func)
2140df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.mox.VerifyAll()
2150df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang
21697d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang    def test_offloader_pubsub_topic_not_set(self):
21797d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        """Test multiprocessing is set."""
21897d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        offload_func = self._mock_get_offload_func(True, False)
21997d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        offloader = gs_offloader.Offloader(_get_options([]))
22097d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.assertEqual(offloader._offload_func,
22197d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang                         offload_func)
22297d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.mox.VerifyAll()
22397d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
22497d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang    def test_offloader_pubsub_topic_set(self):
22597d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        """Test multiprocessing is set."""
22697d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        offload_func = self._mock_get_offload_func(True, False, 'test-topic')
22797d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        offloader = gs_offloader.Offloader(_get_options(['-t', 'test-topic']))
22897d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.assertEqual(offloader._offload_func,
22997d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang                         offload_func)
23097d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.mox.VerifyAll()
23197d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
232f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi
233ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnettedef _make_timestamp(age_limit, is_expired):
2345ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    """Create a timestamp for use by `job_directories.is_job_expired()`.
235ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
236ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    The timestamp will meet the syntactic requirements for
2375ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    timestamps used as input to `is_job_expired()`.  If
238ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `is_expired` is true, the timestamp will be older than
239ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `age_limit` days before the current time; otherwise, the
240ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    date will be younger.
241ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
242ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    @param age_limit    The number of days before expiration of the
243ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        target timestamp.
244ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    @param is_expired   Whether the timestamp should be expired
245ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        relative to `age_limit`.
246ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
247ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
248ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    seconds = -_MARGIN_SECS
249ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    if is_expired:
250ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        seconds = -seconds
251ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    delta = datetime.timedelta(days=age_limit, seconds=seconds)
252ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    reference_time = datetime.datetime.now() - delta
253dfea368e5c830b1d7950ced5ee7b191e3b141ca3Dan Shi    return reference_time.strftime(time_utils.TIME_FMT)
254ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
255ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
256ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass JobExpirationTests(unittest.TestCase):
2575ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    """Tests to exercise `job_directories.is_job_expired()`."""
258ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
259ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_expired(self):
260ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test detection of an expired job."""
261ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        timestamp = _make_timestamp(_TEST_EXPIRATION_AGE, True)
262ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(
2635ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow            job_directories.is_job_expired(
264ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                _TEST_EXPIRATION_AGE, timestamp))
265ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
266ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
267ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_alive(self):
268ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test detection of a job that's not expired."""
269ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # N.B.  This test may fail if its run time exceeds more than
270ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # about _MARGIN_SECS seconds.
271ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        timestamp = _make_timestamp(_TEST_EXPIRATION_AGE, False)
272ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(
2735ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow            job_directories.is_job_expired(
274ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                _TEST_EXPIRATION_AGE, timestamp))
275ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
276ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
277ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass _MockJobDirectory(job_directories._JobDirectory):
278ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Subclass of `_JobDirectory` used as a helper for tests."""
279ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
280ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    GLOB_PATTERN = '[0-9]*-*'
281ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
28224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
283ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def __init__(self, resultsdir):
284ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Create new job in initial state."""
285ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(_MockJobDirectory, self).__init__(resultsdir)
286ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._timestamp = None
2875ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.queue_args = [resultsdir, os.path.dirname(resultsdir), self._timestamp]
288ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
28924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
290ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def get_timestamp_if_finished(self):
291ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        return self._timestamp
292ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
29324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
294ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_finished(self, days_old):
295ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job appear to be finished.
296ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
297ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        After calling this function, calls to `enqueue_offload()`
298ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        will find this job as finished, but not expired and ready
299ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for offload.  Note that when `days_old` is 0,
300ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `enqueue_offload()` will treat a finished job as eligible
301ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for offload.
302ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
303ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param days_old The value of the `days_old` parameter that
304ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        will be passed to `enqueue_offload()` for
305ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        testing.
306ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
307ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
308ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._timestamp = _make_timestamp(days_old, False)
3095ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.queue_args[2] = self._timestamp
310ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
31124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
312ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_expired(self, days_old):
313ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job eligible to be offloaded.
314ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
315ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        After calling this function, calls to `offload` will attempt
316ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        to offload this job.
317ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
318ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param days_old The value of the `days_old` parameter that
319ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        will be passed to `enqueue_offload()` for
320ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        testing.
321ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
322ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
323ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._timestamp = _make_timestamp(days_old, True)
3245ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.queue_args[2] = self._timestamp
325ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
32624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
327ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_incomplete(self):
328ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job appear to have failed offload just once."""
329ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_count += 1
33022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._first_offload_start = time.time()
331ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        if not os.path.isdir(self._dirname):
332ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            os.mkdir(self._dirname)
333ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
33424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
335ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_reportable(self):
336ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job be reportable."""
337ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.set_incomplete()
33822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._offload_count += 1
339ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
34024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
341ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_complete(self):
342ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job be completed."""
343ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_count += 1
344ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        if os.path.isdir(self._dirname):
345ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            os.rmdir(self._dirname)
346ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
347ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
3481e10e92049f4b2724ea43186083e995e418f9802Simran Basi    def process_gs_instructions(self):
3491e10e92049f4b2724ea43186083e995e418f9802Simran Basi        """Always still offload the job directory."""
3501e10e92049f4b2724ea43186083e995e418f9802Simran Basi        return True
3511e10e92049f4b2724ea43186083e995e418f9802Simran Basi
3521e10e92049f4b2724ea43186083e995e418f9802Simran Basi
3539f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnetteclass CommandListTests(unittest.TestCase):
3549f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette    """Tests for `get_cmd_list()`."""
3559f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
356e93c85778aa8b22aa88482c43092133d59434147MK Ryu    def _command_list_assertions(self, job, use_rsync=True, multi=False):
3579f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        """Call `get_cmd_list()` and check the return value.
3589f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3599f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        Check the following assertions:
3609f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette          * The command name (argv[0]) is 'gsutil'.
361e93c85778aa8b22aa88482c43092133d59434147MK Ryu          * '-m' option (argv[1]) is on when the argument, multi, is True.
3629f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette          * The arguments contain the 'cp' subcommand.
3639f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette          * The next-to-last argument (the source directory) is the
3649f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette            job's `queue_args[0]`.
365dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi          * The last argument (the destination URL) is the job's
366dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi            'queue_args[1]'.
3679f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3689f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        @param job A job with properly calculated arguments to
3699f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette                   `get_cmd_list()`
370e93c85778aa8b22aa88482c43092133d59434147MK Ryu        @param use_rsync True when using 'rsync'. False when using 'cp'.
371e93c85778aa8b22aa88482c43092133d59434147MK Ryu        @param multi True when using '-m' option for gsutil.
3729f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3739f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        """
37424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        test_bucket_uri = 'gs://a-test-bucket'
37524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
37624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        gs_offloader.USE_RSYNC_ENABLED = use_rsync
37724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
37824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        command = gs_offloader.get_cmd_list(
379e93c85778aa8b22aa88482c43092133d59434147MK Ryu                multi, job.queue_args[0],
380e93c85778aa8b22aa88482c43092133d59434147MK Ryu                os.path.join(test_bucket_uri, job.queue_args[1]))
38124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
3829f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self.assertEqual(command[0], 'gsutil')
383e93c85778aa8b22aa88482c43092133d59434147MK Ryu        if multi:
384e93c85778aa8b22aa88482c43092133d59434147MK Ryu            self.assertEqual(command[1], '-m')
3859f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self.assertEqual(command[-2], job.queue_args[0])
38624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
38724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        if use_rsync:
38824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertTrue('rsync' in command)
38924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertEqual(command[-1],
39024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich                             os.path.join(test_bucket_uri, job.queue_args[0]))
39124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        else:
39224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertTrue('cp' in command)
39324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertEqual(command[-1],
39424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich                             os.path.join(test_bucket_uri, job.queue_args[1]))
39524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
3969f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3979f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette    def test_get_cmd_list_regular(self):
3989f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        """Test `get_cmd_list()` as for a regular job."""
3999f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        job = _MockJobDirectory('118-debug')
4009f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self._command_list_assertions(job)
4019f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
40224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
4039f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette    def test_get_cmd_list_special(self):
4049f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        """Test `get_cmd_list()` as for a special job."""
4059f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        job = _MockJobDirectory('hosts/host1/118-reset')
4069f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self._command_list_assertions(job)
4079f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
4089f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
40924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich    def test_get_cmd_list_regular_no_rsync(self):
41024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        """Test `get_cmd_list()` as for a regular job."""
41124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        job = _MockJobDirectory('118-debug')
41224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        self._command_list_assertions(job, use_rsync=False)
41324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
41424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
41524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich    def test_get_cmd_list_special_no_rsync(self):
41624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        """Test `get_cmd_list()` as for a special job."""
41724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        job = _MockJobDirectory('hosts/host1/118-reset')
41824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        self._command_list_assertions(job, use_rsync=False)
41924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
42024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
421e93c85778aa8b22aa88482c43092133d59434147MK Ryu    def test_get_cmd_list_regular_multi(self):
422e93c85778aa8b22aa88482c43092133d59434147MK Ryu        """Test `get_cmd_list()` as for a regular job with True multi."""
423e93c85778aa8b22aa88482c43092133d59434147MK Ryu        job = _MockJobDirectory('118-debug')
424e93c85778aa8b22aa88482c43092133d59434147MK Ryu        self._command_list_assertions(job, multi=True)
425e93c85778aa8b22aa88482c43092133d59434147MK Ryu
426e93c85778aa8b22aa88482c43092133d59434147MK Ryu
427e93c85778aa8b22aa88482c43092133d59434147MK Ryu    def test_get_cmd_list_special_multi(self):
428e93c85778aa8b22aa88482c43092133d59434147MK Ryu        """Test `get_cmd_list()` as for a special job with True multi."""
429e93c85778aa8b22aa88482c43092133d59434147MK Ryu        job = _MockJobDirectory('hosts/host1/118-reset')
430e93c85778aa8b22aa88482c43092133d59434147MK Ryu        self._command_list_assertions(job, multi=True)
431e93c85778aa8b22aa88482c43092133d59434147MK Ryu
432e93c85778aa8b22aa88482c43092133d59434147MK Ryu
43397d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tangclass PubSubTest(mox.MoxTestBase):
43497d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang    """Test the test result notifcation data structure."""
43597d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
43697d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang    def test_create_test_result_notification(self):
43797d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        """Tests the test result notification message."""
438328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        self.mox.StubOutWithMock(site_utils, 'get_moblab_id')
439328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        self.mox.StubOutWithMock(site_utils,
440328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang                                 'get_default_interface_mac_address')
441328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        site_utils.get_default_interface_mac_address().AndReturn(
442328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang            '1c:dc:d1:11:01:e1')
443328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        site_utils.get_moblab_id().AndReturn(
444328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang            'c8386d92-9ad1-11e6-80f5-111111111111')
445328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        self.mox.ReplayAll()
446b45c7237e725d044838840872a118536b549cee3Michael Tang        msg = gs_offloader._create_test_result_notification(
447b45c7237e725d044838840872a118536b549cee3Michael Tang                'gs://test_bucket', '123-moblab')
44897d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.assertEquals(base64.b64encode(
44997d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang            gs_offloader.NEW_TEST_RESULT_MESSAGE), msg['data'])
450328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        self.assertEquals(
451328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang            gs_offloader.NOTIFICATION_VERSION,
452328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang            msg['attributes'][gs_offloader.NOTIFICATION_ATTR_VERSION])
453328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        self.assertEquals(
454328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang            '1c:dc:d1:11:01:e1',
455328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang            msg['attributes'][gs_offloader.NOTIFICATION_ATTR_MOBLAB_MAC])
456328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        self.assertEquals(
457328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang            'c8386d92-9ad1-11e6-80f5-111111111111',
458328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang            msg['attributes'][gs_offloader.NOTIFICATION_ATTR_MOBLAB_ID])
459328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        self.assertEquals(
460b45c7237e725d044838840872a118536b549cee3Michael Tang            'gs://test_bucket/123-moblab',
461328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang            msg['attributes'][gs_offloader.NOTIFICATION_ATTR_GCS_URI])
462328073b9ee29148e5db89f8148a7571cd04f6fbbMichael Tang        self.mox.VerifyAll()
46397d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
46497d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
465dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnetteclass _MockJob(object):
466dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    """Class to mock the return value of `AFE.get_jobs()`."""
467dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def __init__(self, created):
468dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.created_on = created
469dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
470dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
471dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnetteclass _MockHostQueueEntry(object):
472dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    """Class to mock the return value of `AFE.get_host_queue_entries()`."""
473dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def __init__(self, finished):
474dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.finished_on = finished
475dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
476dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
477dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnetteclass _MockSpecialTask(object):
478dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    """Class to mock the return value of `AFE.get_special_tasks()`."""
479dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def __init__(self, finished):
480dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.time_finished = finished
481dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
482dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
4832c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnetteclass JobDirectorySubclassTests(mox.MoxTestBase):
4842c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette    """Test specific to RegularJobDirectory and SpecialJobDirectory.
4853e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
4863e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    This provides coverage for the implementation in both
4873e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    RegularJobDirectory and SpecialJobDirectory.
4883e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
4893e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    """
4903e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
4913e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def setUp(self):
4922c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        super(JobDirectorySubclassTests, self).setUp()
493dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.StubOutWithMock(job_directories._AFE, 'get_jobs')
494dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.StubOutWithMock(job_directories._AFE,
495dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 'get_host_queue_entries')
496dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.StubOutWithMock(job_directories._AFE,
497dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 'get_special_tasks')
4983e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
49924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
5002c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette    def test_regular_job_fields(self):
5012c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """Test the constructor for `RegularJobDirectory`.
5022c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5032c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        Construct a regular job, and assert that the `_dirname`
5042c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        and `_id` attributes are set as expected.
5052c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5062c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """
5072c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        resultsdir = '118-fubar'
5082c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.RegularJobDirectory(resultsdir)
5092c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        self.assertEqual(job._dirname, resultsdir)
510cf4d2032ea4bf5af680383f36308d581876bbbb0Dan Shi        self.assertEqual(job._id, 118)
5112c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
51224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
5132c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette    def test_special_job_fields(self):
5142c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """Test the constructor for `SpecialJobDirectory`.
5152c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5162c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        Construct a special job, and assert that the `_dirname`
5172c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        and `_id` attributes are set as expected.
5182c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5192c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """
5202c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        destdir = 'hosts/host1'
5212c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        resultsdir = destdir + '/118-reset'
5222c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.SpecialJobDirectory(resultsdir)
5232c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        self.assertEqual(job._dirname, resultsdir)
524cf4d2032ea4bf5af680383f36308d581876bbbb0Dan Shi        self.assertEqual(job._id, 118)
5252c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
52624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
527dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def _check_finished_job(self, jobtime, hqetimes, expected):
528dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        """Mock and test behavior of a finished job.
529dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
530dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        Initialize the mocks for a call to
531dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        `get_timestamp_if_finished()`, then simulate one call.
532dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        Assert that the returned timestamp matches the passed
533dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        in expected value.
534dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
535dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        @param jobtime Time used to construct a _MockJob object.
536dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        @param hqetimes List of times used to construct
537dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        _MockHostQueueEntry objects.
538dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        @param expected Expected time to be returned by
539dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        get_timestamp_if_finished
540dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
541dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        """
542dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job = job_directories.RegularJobDirectory('118-fubar')
543dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_jobs(
544dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, finished=True).AndReturn(
545dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        [_MockJob(jobtime)])
546dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_host_queue_entries(
547dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                finished_on__isnull=False,
548dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                job_id=job._id).AndReturn(
549dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        [_MockHostQueueEntry(t) for t in hqetimes])
550dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.ReplayAll()
551dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.assertEqual(expected, job.get_timestamp_if_finished())
552dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
553dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
554dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
5553e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_finished_regular_job(self):
5563e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for a finished regular job.
5573e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
5583e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
5593e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `RegularJobDirectory.get_timestamp_if_finished()` when
5603e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is finished.
5613e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
5623e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
563dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        created_timestamp = _make_timestamp(1, True)
564dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        hqe_timestamp = _make_timestamp(0, True)
565dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(created_timestamp,
566dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 [hqe_timestamp],
567dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 hqe_timestamp)
568fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
56924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
570fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi    def test_finished_regular_job_multiple_hqes(self):
571fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """Test getting the timestamp for a regular job with multiple hqes.
572fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
573fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        Tests the return value for
574fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        `RegularJobDirectory.get_timestamp_if_finished()` when
575fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        the AFE indicates the job is finished and the job has multiple host
576fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        queue entries.
577fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
578dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        Tests that the returned timestamp is the latest timestamp in
579dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        the list of HQEs, regardless of the returned order.
580dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
581fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """
582fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        created_timestamp = _make_timestamp(2, True)
583fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        older_hqe_timestamp = _make_timestamp(1, True)
584fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        newer_hqe_timestamp = _make_timestamp(0, True)
585dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        hqe_list = [older_hqe_timestamp,
586dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                    newer_hqe_timestamp]
587dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(created_timestamp,
588dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 hqe_list,
589dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 newer_hqe_timestamp)
590dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.ResetAll()
591dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        hqe_list.reverse()
592dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(created_timestamp,
593dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 hqe_list,
594dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 newer_hqe_timestamp)
595fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
59624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
597fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi    def test_finished_regular_job_null_finished_times(self):
598fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """Test getting the timestamp for an aborted regular job.
599fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
600fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        Tests the return value for
601fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        `RegularJobDirectory.get_timestamp_if_finished()` when
602fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        the AFE indicates the job is finished and the job has aborted host
603fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        queue entries.
604fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
605fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """
606fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        timestamp = _make_timestamp(0, True)
607dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(timestamp, [], timestamp)
6083e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
60924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6103e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_unfinished_regular_job(self):
6113e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for an unfinished regular job.
6123e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6133e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
6143e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `RegularJobDirectory.get_timestamp_if_finished()` when
6153e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is not finished.
6163e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6173e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
6183e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        job = job_directories.RegularJobDirectory('118-fubar')
619dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_jobs(
620dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, finished=True).AndReturn([])
6213e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.mox.ReplayAll()
6223e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.assertIsNone(job.get_timestamp_if_finished())
623dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
6243e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
62524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6263e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_finished_special_job(self):
6273e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for a finished special job.
6283e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6293e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
6303e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `SpecialJobDirectory.get_timestamp_if_finished()` when
6313e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is finished.
6323e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6333e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
6342c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.SpecialJobDirectory(
6352c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette                'hosts/host1/118-reset')
6363e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        timestamp = _make_timestamp(0, True)
637dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_special_tasks(
638dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, is_complete=True).AndReturn(
639dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                    [_MockSpecialTask(timestamp)])
6403e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.mox.ReplayAll()
6413e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.assertEqual(timestamp,
6423e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette                         job.get_timestamp_if_finished())
643dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
6443e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
64524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6463e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_unfinished_special_job(self):
6473e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for an unfinished special job.
6483e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6493e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
6503e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `SpecialJobDirectory.get_timestamp_if_finished()` when
6513e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is not finished.
6523e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6533e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
6542c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.SpecialJobDirectory(
6552c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette                'hosts/host1/118-reset')
656dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_special_tasks(
657dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, is_complete=True).AndReturn([])
6583e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.mox.ReplayAll()
6593e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.assertIsNone(job.get_timestamp_if_finished())
660dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
6613e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6623e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
663ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass _TempResultsDirTestBase(mox.MoxTestBase):
664ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Base class for tests using a temporary results directory."""
665ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
6660880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    REGULAR_JOBLIST = [
6670880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        '111-fubar', '112-fubar', '113-fubar', '114-snafu']
6680880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    HOST_LIST = ['host1', 'host2', 'host3']
6690880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    SPECIAL_JOBLIST = [
6700880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        'hosts/host1/333-reset', 'hosts/host1/334-reset',
6710880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        'hosts/host2/444-reset', 'hosts/host3/555-reset']
6720880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
67324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
674ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
675ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(_TempResultsDirTestBase, self).setUp()
6760880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._resultsroot = tempfile.mkdtemp()
6770880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._cwd = os.getcwd()
6780880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.chdir(self._resultsroot)
679ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
68024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
681ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def tearDown(self):
6820880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.chdir(self._cwd)
683ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        shutil.rmtree(self._resultsroot)
684ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(_TempResultsDirTestBase, self).tearDown()
685ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
68624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
687ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def make_job(self, jobdir):
688ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Create a job with results in `self._resultsroot`.
689ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
690ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param jobdir Name of the subdirectory to be created in
691ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                      `self._resultsroot`.
692ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
693ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
6940880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.mkdir(jobdir)
6950880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        return _MockJobDirectory(jobdir)
6960880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
69724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6980880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    def make_job_hierarchy(self):
6990880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        """Create a sample hierarchy of job directories.
7000880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
7010880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        `self.REGULAR_JOBLIST` is a list of directories for regular
7020880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        jobs to be created; `self.SPECIAL_JOBLIST` is a list of
7030880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        directories for special jobs to be created.
7040880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
7050880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        """
7060880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
7070880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(d)
7080880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        hostsdir = 'hosts'
7090880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.mkdir(hostsdir)
7100880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for host in self.HOST_LIST:
7110880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(os.path.join(hostsdir, host))
7120880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.SPECIAL_JOBLIST:
7130880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(d)
714ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
715ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
71680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhuclass FailedOffloadsLogTest(_TempResultsDirTestBase):
71780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    """Test the formatting of failed offloads log file."""
71880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # Below is partial sample of a failed offload log file.  This text is
71980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # deliberately hard-coded and then parsed to create the test data; the idea
72080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # is to make sure the actual text format will be reviewed by a human being.
72180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    #
72280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # first offload      count  directory
72380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # --+----1----+----  ----+ ----+----1----+----2----+----3
72480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    _SAMPLE_DIRECTORIES_REPORT = '''\
72580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    =================== ======  ==============================
72680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:09:26      1  118-fubar
72780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:19:23      2  117-fubar
72880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:29:20      6  116-fubar
72980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:39:17     24  115-fubar
73080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:49:14    120  114-fubar
73180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:59:11    720  113-fubar
73280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 16:09:08   5040  112-fubar
73380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 16:19:05  40320  111-fubar
73480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    '''
73580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
73680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    def setUp(self):
73780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        super(FailedOffloadsLogTest, self).setUp()
73880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self._offloader = gs_offloader.Offloader(_get_options([]))
73980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self._joblist = []
74080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        for line in self._SAMPLE_DIRECTORIES_REPORT.split('\n')[1 : -1]:
74180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            date_, time_, count, dir_ = line.split()
74280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            job = _MockJobDirectory(dir_)
74380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            job._offload_count = int(count)
74480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            timestruct = time.strptime("%s %s" % (date_, time_),
74580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                                       gs_offloader.FAILED_OFFLOADS_TIME_FORMAT)
74680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            job._first_offload_start = time.mktime(timestruct)
74780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            # enter the jobs in reverse order, to make sure we
74880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            # test that the output will be sorted.
74980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            self._joblist.insert(0, job)
75080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
75180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
75280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    def assert_report_well_formatted(self, report_file):
75380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        with open(report_file, 'r') as f:
75480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            report_lines = f.read().split()
75580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
75680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        for end_of_header_index in range(len(report_lines)):
75780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            if report_lines[end_of_header_index].startswith('=='):
75880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                break
75980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self.assertLess(end_of_header_index, len(report_lines),
76080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                        'Failed to find end-of-header marker in the report')
76180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
76280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        relevant_lines = report_lines[end_of_header_index:]
76380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        expected_lines = self._SAMPLE_DIRECTORIES_REPORT.split()
76480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self.assertListEqual(relevant_lines, expected_lines)
76580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
76680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
76780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    def test_failed_offload_log_format(self):
76880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        """Trigger an e-mail report and check its contents."""
76980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        log_file = os.path.join(self._resultsroot, 'failed_log')
77080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        report = self._offloader._log_failed_jobs_locally(self._joblist,
77180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                                                          log_file=log_file)
77280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self.assert_report_well_formatted(log_file)
77380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
77480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
77580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    def test_failed_offload_file_overwrite(self):
77680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        """Verify that we can saefly overwrite the log file."""
77780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        log_file = os.path.join(self._resultsroot, 'failed_log')
77880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        with open(log_file, 'w') as f:
77980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            f.write('boohoohoo')
78080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        report = self._offloader._log_failed_jobs_locally(self._joblist,
78180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                                                          log_file=log_file)
78280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self.assert_report_well_formatted(log_file)
78380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
78480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
7852e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnetteclass OffloadDirectoryTests(_TempResultsDirTestBase):
7862e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    """Tests for `offload_dir()`."""
7872e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
7882e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def setUp(self):
7892e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        super(OffloadDirectoryTests, self).setUp()
7902e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        # offload_dir() logs messages; silence them.
7912e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._saved_loglevel = logging.getLogger().getEffectiveLevel()
7922e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        logging.getLogger().setLevel(logging.CRITICAL+1)
7932e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._job = self.make_job(self.REGULAR_JOBLIST[0])
7942e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.StubOutWithMock(gs_offloader, 'get_cmd_list')
7952e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.StubOutWithMock(signal, 'alarm')
7962d981eee42e4f9fb4f6d726b97aa8122322543beNingning Xia        self.mox.StubOutWithMock(models.test, 'parse_job_keyval')
7972e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
79824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
7992e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def tearDown(self):
8002e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        logging.getLogger().setLevel(self._saved_loglevel)
8012e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        super(OffloadDirectoryTests, self).tearDown()
8022e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8034211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia    def _mock_upload_testresult_files(self):
8044211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self.mox.StubOutWithMock(gs_offloader, 'upload_testresult_files')
8054211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        gs_offloader.upload_testresult_files(
8064211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia                mox.IgnoreArg(),mox.IgnoreArg()).AndReturn(None)
80724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8085ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    def _mock_create_marker_file(self):
8095ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.mox.StubOutWithMock(__builtin__, 'open')
8105ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        mock_marker_file = self.mox.CreateMock(file)
8115ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        open(mox.IgnoreArg(), 'a').AndReturn(mock_marker_file)
8125ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        mock_marker_file.close()
8135ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow
8145ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow
8155ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    def _mock_offload_dir_calls(self, command, queue_args,
8165ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                                marker_initially_exists=False,
8175ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                                marker_eventually_exists=True):
8182e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Mock out the calls needed by `offload_dir()`.
8192e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8202e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        This covers only the calls made when there is no timeout.
8212e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8222e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        @param command Command list to be returned by the mocked
8232e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                       call to `get_cmd_list()`.
8242e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8252e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
8265ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.mox.StubOutWithMock(os.path, 'isfile')
8275ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        os.path.isfile(mox.IgnoreArg()).AndReturn(marker_initially_exists)
8282e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(gs_offloader.OFFLOAD_TIMEOUT_SECS)
829dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        command.append(queue_args[0])
8302e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        gs_offloader.get_cmd_list(
831e93c85778aa8b22aa88482c43092133d59434147MK Ryu                False, queue_args[0],
832e93c85778aa8b22aa88482c43092133d59434147MK Ryu                '%s%s' % (utils.DEFAULT_OFFLOAD_GSURI,
833e93c85778aa8b22aa88482c43092133d59434147MK Ryu                          queue_args[1])).AndReturn(command)
8344211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self._mock_upload_testresult_files()
8352e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0)
8362e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0)
8375ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        os.path.isfile(mox.IgnoreArg()).AndReturn(marker_eventually_exists)
8382e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
83924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8405ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    def _run_offload_dir(self, should_succeed, delete_age):
8412e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Make one call to `offload_dir()`.
8422e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8432e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        The caller ensures all mocks are set up already.
8442e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8452e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        @param should_succeed True iff the call to `offload_dir()`
8462e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                              is expected to succeed and remove the
8472e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                              offloaded job directory.
8482e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8492e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
8502e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.ReplayAll()
851dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        gs_offloader.get_offload_dir_func(
8525ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                utils.DEFAULT_OFFLOAD_GSURI, False, delete_age)(
853e93c85778aa8b22aa88482c43092133d59434147MK Ryu                        self._job.queue_args[0],
8545ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                        self._job.queue_args[1],
8555ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                        self._job.queue_args[2])
8562e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.VerifyAll()
8572e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.assertEqual(not should_succeed,
8582e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                         os.path.isdir(self._job.queue_args[0]))
8592e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
86024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8612e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_success(self):
8622e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` can succeed correctly."""
863dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self._mock_offload_dir_calls(['test', '-d'],
864dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                                     self._job.queue_args)
8655ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self._mock_create_marker_file()
8665ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self._run_offload_dir(True, 0)
8672e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
86824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8692e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_failure(self):
8702e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` can fail correctly."""
871dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self._mock_offload_dir_calls(['test', '!', '-d'],
8725ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                                     self._job.queue_args,
8735ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                                     marker_eventually_exists=False)
8745ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self._run_offload_dir(False, 0)
8752e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
87624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8772e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_timeout_early(self):
8782e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` times out correctly.
8792e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8802e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        This test triggers timeout at the earliest possible moment,
8812e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        at the first call to set the timeout alarm.
8822e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8832e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
8844211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self._mock_upload_testresult_files()
8852e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(gs_offloader.OFFLOAD_TIMEOUT_SECS).AndRaise(
8862e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                        gs_offloader.TimeoutException('fubar'))
8872e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0)
8885ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self._run_offload_dir(False, 0)
8892e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
89024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8912e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_timeout_late(self):
8922e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` times out correctly.
8932e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8942e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        This test triggers timeout at the latest possible moment, at
8952e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        the call to clear the timeout alarm.
8962e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8972e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
8982e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(gs_offloader.OFFLOAD_TIMEOUT_SECS)
8992e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        gs_offloader.get_cmd_list(
900e93c85778aa8b22aa88482c43092133d59434147MK Ryu                False, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
9012e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                        ['test', '-d', self._job.queue_args[0]])
9024211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self._mock_upload_testresult_files()
9032e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0).AndRaise(
9042e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                gs_offloader.TimeoutException('fubar'))
9052e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0)
9065ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self._run_offload_dir(False, 0)
9072e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
9082e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
909affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi    def test_sanitize_dir(self):
910affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        """Test that folder/file name with invalid character can be corrected.
911affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        """
912affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        results_folder = tempfile.mkdtemp()
913affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_chars = '_'.join(gs_offloader.INVALID_GS_CHARS)
914affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_files = []
915affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_folder = os.path.join(
916affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                results_folder,
917affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                'invalid_name_folder_%s' % invalid_chars)
918affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_files.append(os.path.join(
919affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                invalid_folder,
920affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                'invalid_name_file_%s' % invalid_chars))
921affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for r in gs_offloader.INVALID_GS_CHAR_RANGE:
922affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            for c in range(r[0], r[1]+1):
923affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                # NULL cannot be in file name.
924affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                if c != 0:
925affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                    invalid_files.append(os.path.join(
926affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                            invalid_folder,
927affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                            'invalid_name_file_%s' % chr(c)))
928affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        good_folder =  os.path.join(results_folder, 'valid_name_folder')
929affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        good_file = os.path.join(good_folder, 'valid_name_file')
930affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for folder in [invalid_folder, good_folder]:
931affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            os.makedirs(folder)
932affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for f in invalid_files + [good_file]:
933affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            with open(f, 'w'):
934affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                pass
935affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        gs_offloader.sanitize_dir(results_folder)
936affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for _, dirs, files in os.walk(results_folder):
937affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            for name in dirs + files:
938affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                self.assertEqual(name, gs_offloader.get_sanitized_name(name))
939affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                for c in name:
940affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                    self.assertFalse(c in gs_offloader.INVALID_GS_CHARS)
941affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                    for r in gs_offloader.INVALID_GS_CHAR_RANGE:
942affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                        self.assertFalse(ord(c) >= r[0] and ord(c) <= r[1])
943affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        self.assertTrue(os.path.exists(good_file))
944affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        shutil.rmtree(results_folder)
945affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi
946affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi
9471b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi    def check_limit_file_count(self, is_test_job=True):
9481b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """Test that folder with too many files can be compressed.
9491b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9501b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        @param is_test_job: True to check the method with test job result
9511b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                            folder. Set to False for special task folder.
9521b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """
9531b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        results_folder = tempfile.mkdtemp()
9541b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        host_folder = os.path.join(
9551b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                results_folder,
9561b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                'lab1-host1' if is_test_job else 'hosts/lab1-host1/1-repair')
9571b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        debug_folder = os.path.join(host_folder, 'debug')
9581b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        sysinfo_folder = os.path.join(host_folder, 'sysinfo')
9591b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        for folder in [debug_folder, sysinfo_folder]:
9601b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi            os.makedirs(folder)
9611b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi            for i in range(10):
9621b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                with open(os.path.join(folder, str(i)), 'w') as f:
9631b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                    f.write('test')
9641b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9651b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.MAX_FILE_COUNT = 100
9661b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.limit_file_count(
9671b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                results_folder if is_test_job else host_folder)
9681b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertTrue(os.path.exists(sysinfo_folder))
9691b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9701b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.MAX_FILE_COUNT = 10
9711b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.limit_file_count(
9721b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                results_folder if is_test_job else host_folder)
9731b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertFalse(os.path.exists(sysinfo_folder))
9741b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertTrue(os.path.exists(sysinfo_folder + '.tgz'))
9751b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertTrue(os.path.exists(debug_folder))
9761b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9771b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        shutil.rmtree(results_folder)
9781b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9791b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9801b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi    def test_limit_file_count(self):
9811b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """Test that folder with too many files can be compressed.
9821b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """
9831b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.check_limit_file_count(is_test_job=True)
9841b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.check_limit_file_count(is_test_job=False)
9851b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9862d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
9878db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia    def test_is_valid_result(self):
9888db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        """Test _is_valid_result."""
98921922c807733cab1a86096500304aa8ae68bd897Ningning Xia        release_build = 'veyron_minnie-cheets-release/R52-8248.0.0'
99021922c807733cab1a86096500304aa8ae68bd897Ningning Xia        pfq_build = 'cyan-cheets-android-pfq/R54-8623.0.0-rc1'
99121922c807733cab1a86096500304aa8ae68bd897Ningning Xia        trybot_build = 'trybot-samus-release/R54-8640.0.0-b5092'
99221922c807733cab1a86096500304aa8ae68bd897Ningning Xia        trybot_2_build = 'trybot-samus-pfq/R54-8640.0.0-b5092'
99321922c807733cab1a86096500304aa8ae68bd897Ningning Xia        release_2_build = 'test-trybot-release/R54-8640.0.0-b5092'
9948db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertTrue(gs_offloader._is_valid_result(
9958db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
9966384c1094ddf148de5d3ff16aed1bbab077b5f26Rohit Makasana        self.assertTrue(gs_offloader._is_valid_result(
9976384c1094ddf148de5d3ff16aed1bbab077b5f26Rohit Makasana            release_build, gs_offloader.CTS_RESULT_PATTERN, 'test_that_wrapper'))
9988db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
9998db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-bvt-cq'))
10008db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertTrue(gs_offloader._is_valid_result(
10018db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.GTS_RESULT_PATTERN, 'arc-gts-tot'))
10028db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
10038db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            None, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
10048db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
10058db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.CTS_RESULT_PATTERN, None))
10068db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
10078db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            pfq_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
10088db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
10098db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            trybot_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
10108db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
10118db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            trybot_2_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
10128db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertTrue(gs_offloader._is_valid_result(
10138db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_2_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
101421922c807733cab1a86096500304aa8ae68bd897Ningning Xia
101521922c807733cab1a86096500304aa8ae68bd897Ningning Xia
10160c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia    def create_results_folder(self):
10170c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        """Create CTS/GTS results folders."""
10184211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        results_folder = tempfile.mkdtemp()
10194211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        host_folder = os.path.join(results_folder, 'chromeos4-row9-rack11-host22')
10204211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        debug_folder = os.path.join(host_folder, 'debug')
10214211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        sysinfo_folder = os.path.join(host_folder, 'sysinfo')
10224211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        cts_result_folder = os.path.join(
10234211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia                host_folder, 'cheets_CTS.android.dpi', 'results', 'cts-results')
10242d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        gts_result_folder = os.path.join(
1025bfa63148ef62dc36e2d4b3456a4b64ae69b21172Ilja H. Friedel                host_folder, 'cheets_GTS.google.admin', 'results', 'android-gts')
10264211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        timestamp_str = '2016.04.28_01.41.44'
10272d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        timestamp_cts_folder = os.path.join(cts_result_folder, timestamp_str)
10282d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        timestamp_gts_folder = os.path.join(gts_result_folder, timestamp_str)
10292d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10300c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        # Test results in cts_result_folder with a different time-stamp.
10310c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        timestamp_str_2 = '2016.04.28_10.41.44'
10320c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        timestamp_cts_folder_2 = os.path.join(cts_result_folder, timestamp_str_2)
10330c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10342d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        for folder in [debug_folder, sysinfo_folder, cts_result_folder,
10350c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                       timestamp_cts_folder, timestamp_gts_folder, timestamp_cts_folder_2]:
10364211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia            os.makedirs(folder)
10372d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10380c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        path_pattern_pair = [(timestamp_cts_folder, gs_offloader.CTS_RESULT_PATTERN),
10390c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                             (timestamp_cts_folder_2, gs_offloader.CTS_RESULT_PATTERN),
10400c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                             (timestamp_gts_folder, gs_offloader.GTS_RESULT_PATTERN)]
10414211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
10420c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        # Create timestamp.zip file_path.
10430c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_zip_file = os.path.join(cts_result_folder, timestamp_str + '.zip')
10440c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_zip_file_2 = os.path.join(cts_result_folder, timestamp_str_2 + '.zip')
10452d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        gts_zip_file = os.path.join(gts_result_folder, timestamp_str + '.zip')
10464211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
10470c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        # Create xml file_path.
10480c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_result_file = os.path.join(timestamp_cts_folder, 'testResult.xml')
10490c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_result_file_2 = os.path.join(timestamp_cts_folder_2, 'testResult.xml')
1050bfa63148ef62dc36e2d4b3456a4b64ae69b21172Ilja H. Friedel        gts_result_file = os.path.join(timestamp_gts_folder, 'test_result.xml')
10512d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10520c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        for file_path in [cts_zip_file, cts_zip_file_2, gts_zip_file,
10530c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                          cts_result_file, cts_result_file_2, gts_result_file]:
10540c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            with open(file_path, 'w') as f:
10550c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                f.write('test')
10562d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10570c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        return (results_folder, host_folder, path_pattern_pair)
10582d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10590c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10600c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia    def test_upload_testresult_files(self):
10610c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        """Test upload_testresult_files."""
10620c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        results_folder, host_folder, path_pattern_pair = self.create_results_folder()
10630c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10640c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        self.mox.StubOutWithMock(gs_offloader, '_upload_files')
10650c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        gs_offloader._upload_files(
10660c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn(
10670c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                ['test', '-d', host_folder])
10680c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        gs_offloader._upload_files(
10690c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn(
10700c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                ['test', '-d', host_folder])
10710c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        gs_offloader._upload_files(
10720c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn(
10730c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                ['test', '-d', host_folder])
10744211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
10754211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self.mox.ReplayAll()
10764211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        gs_offloader.upload_testresult_files(results_folder, False)
10774211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self.mox.VerifyAll()
10780c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        shutil.rmtree(results_folder)
10790c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10800c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10810c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia    def test_upload_files(self):
10820c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        """Test upload_files"""
10830c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        results_folder, host_folder, path_pattern_pair = self.create_results_folder()
10840c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10850c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        for path, pattern in path_pattern_pair:
10860c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            models.test.parse_job_keyval(mox.IgnoreArg()).AndReturn({
10870c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                'build': 'veyron_minnie-cheets-release/R52-8248.0.0',
10888db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia                'parent_job_id': 'p_id',
10898db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia                'suite': 'arc-cts'
10900c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            })
10910c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10920c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            gs_offloader.get_cmd_list(
10930c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                False, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
10940c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                    ['test', '-d', path])
10950c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            gs_offloader.get_cmd_list(
10960c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                False, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
10970c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                    ['test', '-d', path])
10980c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10990c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            self.mox.ReplayAll()
11000c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            gs_offloader._upload_files(host_folder, path, pattern, False)
11010c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            self.mox.VerifyAll()
11020c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            self.mox.ResetAll()
11034211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
11044211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        shutil.rmtree(results_folder)
11051b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
110697d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
1107ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass JobDirectoryOffloadTests(_TempResultsDirTestBase):
1108ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `_JobDirectory.enqueue_offload()`.
1109ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1110ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    When testing with a `days_old` parameter of 0, we use
1111ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `set_finished()` instead of `set_expired()`.  This causes the
1112ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    job's timestamp to be set in the future.  This is done so as
1113ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    to test that when `days_old` is 0, the job is always treated
1114ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    as eligible for offload, regardless of the timestamp's value.
1115ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1116ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    Testing covers the following assertions:
1117ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     A. Each time `enqueue_offload()` is called, a message that
1118ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        includes the job's directory name will be logged using
1119ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `logging.debug()`, regardless of whether the job was
1120ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        enqueued.  Nothing else is allowed to be logged.
1121ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     B. If the job is not eligible to be offloaded,
112222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        `get_failure_time()` and `get_failure_count()` are 0.
1123ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     C. If the job is not eligible for offload, nothing is
1124ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        enqueued in `queue`.
112522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette     D. When the job is offloaded, `get_failure_count()` increments
1126ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        each time.
1127ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     E. When the job is offloaded, the appropriate parameters are
1128ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        enqueued exactly once.
112922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette     F. The first time a job is offloaded, `get_failure_time()` is
1130ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        set to the current time.
113122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette     G. `get_failure_time()` only changes the first time that the
1132ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job is offloaded.
1133ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1134ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    The test cases below are designed to exercise all of the
1135ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    meaningful state transitions at least once.
1136ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1137ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
1138ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1139ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1140ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(JobDirectoryOffloadTests, self).setUp()
11410880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._job = self.make_job(self.REGULAR_JOBLIST[0])
1142ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._queue = Queue.Queue()
1143ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
114424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1145ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _offload_unexpired_job(self, days_old):
1146ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make calls to `enqueue_offload()` for an unexpired job.
1147ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1148ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This method tests assertions B and C that calling
1149ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `enqueue_offload()` has no effect.
1150ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1151ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
115222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_count(), 0)
115322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_time(), 0)
115422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._job.enqueue_offload(self._queue, days_old)
115522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._job.enqueue_offload(self._queue, days_old)
1156ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(self._queue.empty())
115722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_count(), 0)
115822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_time(), 0)
115922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertFalse(self._job.is_reportable())
1160ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
116124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1162ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _offload_expired_once(self, days_old, count):
1163ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make one call to `enqueue_offload()` for an expired job.
1164ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1165ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This method tests assertions D and E regarding side-effects
1166ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        expected when a job is offloaded.
1167ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1168ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
116922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._job.enqueue_offload(self._queue, days_old)
117022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_count(), count)
1171ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(self._queue.empty())
1172ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        v = self._queue.get_nowait()
1173ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(self._queue.empty())
11742c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        self.assertEqual(v, self._job.queue_args)
1175ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
117624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1177ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _offload_expired_job(self, days_old):
1178ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make calls to `enqueue_offload()` for a just-expired job.
1179ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1180ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This method directly tests assertions F and G regarding
118122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        side-effects on `get_failure_time()`.
1182ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1183ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1184ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        t0 = time.time()
1185ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_once(days_old, 1)
118622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertFalse(self._job.is_reportable())
118722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        t1 = self._job.get_failure_time()
1188ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertLessEqual(t1, time.time())
1189ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertGreaterEqual(t1, t0)
1190ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_once(days_old, 2)
119122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertTrue(self._job.is_reportable())
119222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_time(), t1)
1193ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_once(days_old, 3)
119422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertTrue(self._job.is_reportable())
119522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_time(), t1)
1196ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
119724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1198ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_1_no_expiration(self):
1199ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` of 0.
1200ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1201ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are
1202ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        made both before and after the job becomes expired.
1203ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1204ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1205ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(0)
1206ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(0)
1207ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(0)
1208ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
120924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1210ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_2_no_expiration(self):
1211ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` of 0.
1212ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1213ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1214ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only after the job becomes expired.
1215ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1216ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1217ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(0)
1218ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(0)
1219ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
122024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1221ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_1_with_expiration(self):
1222ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1223ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1224ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1225ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        before the job finishes, before the job expires, and after
1226ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the job expires.
1227ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1228ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1229ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1230ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(_TEST_EXPIRATION_AGE)
1231ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1232ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1233ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1234ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
123524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1236ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_2_with_expiration(self):
1237ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1238ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1239ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1240ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        between finishing and expiration, and after the job expires.
1241ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1242ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1243ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(_TEST_EXPIRATION_AGE)
1244ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1245ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1246ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1247ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
124824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1249ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_3_with_expiration(self):
1250ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1251ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1252ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1253ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only before finishing and after expiration.
1254ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1255ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1256ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1257ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1258ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1259ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
126024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1261ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_4_with_expiration(self):
1262ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1263ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1264ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1265ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only after expiration.
1266ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1267ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1268ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1269ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1270ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1271ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1272ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass GetJobDirectoriesTests(_TempResultsDirTestBase):
1273ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `_JobDirectory.get_job_directories()`."""
1274ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1275ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1276ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(GetJobDirectoriesTests, self).setUp()
12770880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self.make_job_hierarchy()
12780880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.mkdir('not-a-job')
12790880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        open('not-a-dir', 'w').close()
1280ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
128124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1282ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _run_get_directories(self, cls, expected_list):
1283ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `get_job_directories()` for the given class.
1284ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1285ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Calls the method, and asserts that the returned list of
1286ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        directories matches the expected return value.
1287ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1288ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param expected_list Expected return value from the call.
1289ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1290ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        dirlist = cls.get_job_directories()
1291ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(set(dirlist), set(expected_list))
1292ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
129324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1294ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_get_regular_jobs(self):
1295ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `RegularJobDirectory.get_job_directories()`."""
1296ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_get_directories(job_directories.RegularJobDirectory,
12970880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette                                  self.REGULAR_JOBLIST)
1298ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
129924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1300ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_get_special_jobs(self):
1301ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `SpecialJobDirectory.get_job_directories()`."""
1302ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_get_directories(job_directories.SpecialJobDirectory,
13030880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette                                  self.SPECIAL_JOBLIST)
1304ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1305ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1306ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass AddJobsTests(_TempResultsDirTestBase):
1307ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `Offloader._add_new_jobs()`."""
1308ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
13090880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    MOREJOBS = ['115-fubar', '116-fubar', '117-fubar', '118-snafu']
1310ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1311ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1312ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(AddJobsTests, self).setUp()
131322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._initial_job_names = (
131422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette            set(self.REGULAR_JOBLIST) | set(self.SPECIAL_JOBLIST))
13150880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self.make_job_hierarchy()
13160880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._offloader = gs_offloader.Offloader(_get_options(['-a']))
131722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.StubOutWithMock(logging, 'debug')
1318ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
131924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
132022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette    def _run_add_new_jobs(self, expected_key_set):
1321ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Basic test assertions for `_add_new_jobs()`.
1322ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1323ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Asserts the following:
1324ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The keys in the offloader's `_open_jobs` dictionary
1325ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            matches the expected set of keys.
1326ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * For every job in `_open_jobs`, the job has the expected
1327ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            directory name.
1328ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1329ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
133022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        count = len(expected_key_set) - len(self._offloader._open_jobs)
133122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        logging.debug(mox.IgnoreArg(), count)
133222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.ReplayAll()
133322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._offloader._add_new_jobs()
1334ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(expected_key_set,
1335ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                         set(self._offloader._open_jobs.keys()))
1336ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for jobkey, job in self._offloader._open_jobs.items():
1337ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self.assertEqual(jobkey, job._dirname)
133822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.VerifyAll()
133922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.ResetAll()
1340ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
134124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1342ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_add_jobs_empty(self):
1343ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test adding jobs to an empty dictionary.
1344ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1345ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Calls the offloader's `_add_new_jobs()`, then perform
1346ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the assertions of `self._check_open_jobs()`.
1347ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1348ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
134922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_add_new_jobs(self._initial_job_names)
1350ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
135124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1352ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_add_jobs_non_empty(self):
1353ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test adding jobs to a non-empty dictionary.
1354ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1355ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Calls the offloader's `_add_new_jobs()` twice; once from
1356ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        initial conditions, and then again after adding more
1357ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        directories.  After the second call, perform the assertions
1358ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        of `self._check_open_jobs()`.  Additionally, assert that
1359ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        keys added by the first call still map to their original
1360ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job object after the second call.
1361ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1362ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
136322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_add_new_jobs(self._initial_job_names)
1364ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        jobs_copy = self._offloader._open_jobs.copy()
13650880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.MOREJOBS:
13660880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(d)
136722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_add_new_jobs(self._initial_job_names |
136822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette                                 set(self.MOREJOBS))
1369ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for key in jobs_copy.keys():
1370ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self.assertIs(jobs_copy[key],
1371ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                          self._offloader._open_jobs[key])
1372ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1373ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1374ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass JobStateTests(_TempResultsDirTestBase):
1375ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for job state predicates.
1376ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1377ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    This tests for the expected results from the
1378ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `is_offloaded()` and `is_reportable()` predicate
1379ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    methods.
1380ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1381ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
1382ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1383ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_unfinished_job(self):
1384ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test that an unfinished job reports the correct state.
1385ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1386ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job is "unfinished" if it isn't marked complete in the
1387ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        database.  A job in this state is neither "complete" nor
1388ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        "reportable".
1389ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1390ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
13910880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        job = self.make_job(self.REGULAR_JOBLIST[0])
1392ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_offloaded())
1393ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_reportable())
1394ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
139524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1396ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_incomplete_job(self):
1397ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test that an incomplete job reports the correct state.
1398ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1399ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job is "incomplete" if exactly one attempt has been made
1400ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        to offload the job, but its results directory still exists.
1401ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job in this state is neither "complete" nor "reportable".
1402ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1403ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
14040880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        job = self.make_job(self.REGULAR_JOBLIST[0])
1405ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job.set_incomplete()
1406ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_offloaded())
1407ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_reportable())
1408ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
140924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1410ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_reportable_job(self):
1411ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test that a reportable job reports the correct state.
1412ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1413ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job is "reportable" if more than one attempt has been made
1414ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        to offload the job, and its results directory still exists.
1415ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job in this state is "reportable", but not "complete".
1416ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1417ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
14180880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        job = self.make_job(self.REGULAR_JOBLIST[0])
1419ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job.set_reportable()
1420ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_offloaded())
1421ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(job.is_reportable())
1422ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
142324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1424ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_completed_job(self):
1425ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test that a completed job reports the correct state.
1426ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1427ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job is "completed" if at least one attempt has been made
1428ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        to offload the job, and its results directory still exists.
1429ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job in this state is "complete", and not "reportable".
1430ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1431ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
14320880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        job = self.make_job(self.REGULAR_JOBLIST[0])
1433ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job.set_complete()
1434ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(job.is_offloaded())
1435ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_reportable())
1436ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1437ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1438ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass ReportingTests(_TempResultsDirTestBase):
1439ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `Offloader._update_offload_results()`."""
1440ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1441ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1442ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(ReportingTests, self).setUp()
1443ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader = gs_offloader.Offloader(_get_options([]))
1444ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.StubOutWithMock(email_manager.manager,
1445ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                                 'send_email')
144616f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self.mox.StubOutWithMock(self._offloader, '_log_failed_jobs_locally')
144722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.StubOutWithMock(logging, 'debug')
1448ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
144924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1450ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _add_job(self, jobdir):
1451ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Add a job to the dictionary of unfinished jobs."""
1452ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        j = self.make_job(jobdir)
1453ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader._open_jobs[j._dirname] = j
1454ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        return j
1455ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
145624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
145722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette    def _expect_log_message(self, new_open_jobs, with_failures):
145822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """Mock expected logging calls.
145922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
146022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        `_update_offload_results()` logs one message with the number
146122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        of jobs removed from the open job set and the number of jobs
146222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        still remaining.  Additionally, if there are reportable
146322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        jobs, then it logs the number of jobs that haven't yet
146422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        offloaded.
146522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
146622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        This sets up the logging calls using `new_open_jobs` to
146722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        figure the job counts.  If `with_failures` is true, then
146822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        the log message is set up assuming that all jobs in
146922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        `new_open_jobs` have offload failures.
147022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
147122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        @param new_open_jobs New job set for calculating counts
147222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette                             in the messages.
147322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        @param with_failures Whether the log message with a
147422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette                             failure count is expected.
147522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
147622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """
147722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        count = len(self._offloader._open_jobs) - len(new_open_jobs)
147822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        logging.debug(mox.IgnoreArg(), count, len(new_open_jobs))
147922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        if with_failures:
148022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette            logging.debug(mox.IgnoreArg(), len(new_open_jobs))
148122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
148224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1483ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _run_update_no_report(self, new_open_jobs):
1484ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Call `_update_offload_results()` expecting no report.
1485ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1486ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are set up by the caller.  This calls
1487ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_update_offload_results()` once, and then checks these
1488ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        assertions:
1489ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The offloader's `_next_report_time` field is unchanged.
1490ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The offloader's new `_open_jobs` field contains only
1491ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            the entries in `new_open_jobs`.
1492ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The email_manager's `send_email` stub wasn't called.
1493ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1494ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param new_open_jobs A dictionary representing the expected
1495ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             new value of the offloader's
1496ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             `_open_jobs` field.
1497ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1498ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ReplayAll()
1499ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        next_report_time = self._offloader._next_report_time
1500ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader._update_offload_results()
1501ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(next_report_time,
1502ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                         self._offloader._next_report_time)
1503ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(self._offloader._open_jobs, new_open_jobs)
1504ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.VerifyAll()
1505ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ResetAll()
1506ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
150724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1508ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _run_update_with_report(self, new_open_jobs):
1509ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Call `_update_offload_results()` expecting an e-mail report.
1510ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1511ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are set up by the caller.  This calls
1512ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_update_offload_results()` once, and then checks these
1513ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        assertions:
1514ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The offloader's `_next_report_time` field is updated
1515ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            to an appropriate new time.
1516ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The offloader's new `_open_jobs` field contains only
1517ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            the entries in `new_open_jobs`.
1518ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The email_manager's `send_email` stub was called.
1519ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1520ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param new_open_jobs A dictionary representing the expected
1521ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             new value of the offloader's
1522ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             `_open_jobs` field.
1523ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
152422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        logging.debug(mox.IgnoreArg())
1525ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        email_manager.manager.send_email(
1526ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg())
1527ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ReplayAll()
1528ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        t0 = time.time() + gs_offloader.REPORT_INTERVAL_SECS
1529ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader._update_offload_results()
1530ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        t1 = time.time() + gs_offloader.REPORT_INTERVAL_SECS
1531ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        next_report_time = self._offloader._next_report_time
1532ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertGreaterEqual(next_report_time, t0)
1533ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertLessEqual(next_report_time, t1)
1534ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(self._offloader._open_jobs, new_open_jobs)
1535ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.VerifyAll()
1536ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ResetAll()
1537ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
153824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
153916f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu    def _expect_failed_jobs(self, failed_jobs):
154016f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        """Mock expected call to log the failed jobs on local disk.
154116f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu
154216f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        TODO(crbug.com/686904): The fact that we have to mock an internal
154316f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        function for this test is evidence that we need to pull out the local
154416f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        file formatter in its own object in a future CL.
154516f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu
154616f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        @param failed_jobs: The list of jobs being logged as failed.
154716f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        """
154816f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._offloader._log_failed_jobs_locally(failed_jobs)
154916f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu
155016f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu
1551ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_no_jobs(self):
1552ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with no open jobs.
1553ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1554ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an empty `_open_jobs` list and
1555ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_next_report_time` in the past.  Expected result is no
1556ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        e-mail report, and an empty `_open_jobs` list.
1557ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1558ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
155922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message({}, False)
156016f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs([])
1561ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_update_no_report({})
1562ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
156324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1564ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_all_completed(self):
1565ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with only complete jobs.
1566ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1567ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1568ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only completed jobs and `_next_report_time` in the past.
1569ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Expected result is no e-mail report, and an empty
1570ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_open_jobs` list.
1571ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1572ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
15730880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1574ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d).set_complete()
157522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message({}, False)
157616f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs([])
1577ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_update_no_report({})
1578ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
157924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1580ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_none_finished(self):
1581ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with only unfinished jobs.
1582ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1583ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1584ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only unfinished jobs and `_next_report_time` in the past.
1585ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Expected result is no e-mail report, and no change to the
1586ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_open_jobs` list.
1587ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1588ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
15890880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1590ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d)
159122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
159222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, False)
159316f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs([])
159422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_no_report(new_jobs)
1595ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
159624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1597ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_none_reportable(self):
1598ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with only incomplete jobs.
1599ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1600ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1601ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only incomplete jobs and `_next_report_time` in the past.
1602ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Expected result is no e-mail report, and no change to the
1603ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_open_jobs` list.
1604ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1605ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
16060880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1607ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d).set_incomplete()
160822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
160922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, False)
161016f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs(mox.IgnoreArg())
161122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_no_report(new_jobs)
1612ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
161324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1614ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_report_not_ready(self):
1615ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` e-mail throttling.
1616ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1617ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1618ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only reportable jobs but with `_next_report_time` in
1619ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the future.  Expected result is no e-mail report, and no
1620ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        change to the `_open_jobs` list.
1621ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1622ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1623ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # N.B.  This test may fail if its run time exceeds more than
1624ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # about _MARGIN_SECS seconds.
16250880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1626ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d).set_reportable()
1627ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader._next_report_time += _MARGIN_SECS
162822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
162922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, True)
163016f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs(mox.IgnoreArg())
163122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_no_report(new_jobs)
1632ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
163324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1634ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_reportable(self):
1635ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with reportable jobs.
1636ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1637ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1638ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only reportable jobs and with `_next_report_time` in
1639ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the past.  Expected result is an e-mail report, and no
1640ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        change to the `_open_jobs` list.
1641ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1642ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
16430880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1644ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d).set_reportable()
164522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
164622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, True)
164716f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs(mox.IgnoreArg())
164822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_with_report(new_jobs)
164922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
165024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
165122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette    def test_reportable_mixed(self):
165222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """Test `_update_offload_results()` with a mixture of jobs.
165322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
165422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
165522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        one reportable jobs and the remainder of the jobs
165622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        incomplete.  The value of `_next_report_time` is in the
165722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        past.  Expected result is an e-mail report that includes
165822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        both the reportable and the incomplete jobs, and no change
165922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        to the `_open_jobs` list.
166022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
166122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """
166222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._add_job(self.REGULAR_JOBLIST[0]).set_reportable()
166322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        for d in self.REGULAR_JOBLIST[1:]:
166422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette            self._add_job(d).set_incomplete()
166522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
166622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, True)
166716f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs(mox.IgnoreArg())
166822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_with_report(new_jobs)
1669ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1670ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1671ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteif __name__ == '__main__':
1672ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    unittest.main()
1673