gs_offloader_unittest.py revision 6384c1094ddf148de5d3ff16aed1bbab077b5f26
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
5ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport Queue
697d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tangimport base64
7ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport datetime
8ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport logging
9ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport os
10ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport shutil
112e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnetteimport signal
12ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport sys
13ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport tempfile
14ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport time
15ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport unittest
16ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
17ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport mox
18ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
19ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport common
20ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport gs_offloader
21ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport job_directories
22ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
23dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basifrom autotest_lib.client.common_lib import global_config
241b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shifrom autotest_lib.client.common_lib import time_utils
251b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shifrom autotest_lib.client.common_lib import utils
26ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnettefrom autotest_lib.scheduler import email_manager
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,
6997d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang                               pubsub_topic=None):
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)
790df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offload_func = gs_offloader.get_offload_dir_func(
800df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang                expected_gsuri, multiprocessing)
81dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.mox.StubOutWithMock(gs_offloader, 'get_offload_dir_func')
8297d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        gs_offloader.get_offload_dir_func(expected_gsuri, multiprocessing,
8397d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang                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)
97ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._age_limit, 0)
98ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
9924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
100ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_process_all_option(self):
101ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --all option."""
102dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(False)
103ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(_get_options(['--all']))
104ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes), self._BOTH)
105ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
106ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
107dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
108ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._age_limit, 0)
109ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
11024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
111ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_process_hosts_option(self):
112ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --hosts option."""
113dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(False)
114ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
115ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--hosts']))
116ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
117ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._SPECIAL_ONLY)
118ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
119ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
120dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
121ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._age_limit, 0)
122ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
12324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
124ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_parallelism_option(self):
125ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --parallelism option."""
126dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(False)
127ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
128ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--parallelism', '2']))
129ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
130ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
131ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 2)
132ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
133dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
134ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._age_limit, 0)
135ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
13624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
137ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_delete_only_option(self):
138ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --delete_only option."""
139ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
140ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--delete_only']))
141ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
142ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
143ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
144ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
145ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         gs_offloader.delete_files)
146ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._age_limit, 0)
14797d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.assertIsNone(offloader._pubsub_topic)
148ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
14924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
150df4751eaab3405bc4f564d033681d093958f0c10Simran Basi    def test_days_old_option(self):
151ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --days_old option."""
152dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(False)
153ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
154ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--days_old', '7']))
155ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
156ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
157ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
158ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._offload_func,
159dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
160ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._age_limit, 7)
161ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
16224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
163dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi    def test_moblab_gsuri_generation(self):
164dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        """Test offloader construction for Moblab."""
165dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offload_func = self._mock_get_offload_func(True)
166dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offloader = gs_offloader.Offloader(_get_options([]))
167dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.assertEqual(set(offloader._jobdir_classes),
168dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         self._REGULAR_ONLY)
169dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.assertEqual(offloader._processes, 1)
170dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.assertEqual(offloader._offload_func,
171dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         offload_func)
172dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.assertEqual(offloader._age_limit, 0)
173dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi
174ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
175f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi    def test_globalconfig_offloading_flag(self):
176f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        """Test enabling of --delete_only via global_config."""
177f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        gs_offloader.GS_OFFLOADING_ENABLED = False
178f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        offloader = gs_offloader.Offloader(
179f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi                _get_options([]))
180f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        self.assertEqual(offloader._offload_func,
181f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi                         gs_offloader.delete_files)
182f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi
1830df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang    def test_offloader_multiprocessing_flag_set(self):
1840df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        """Test multiprocessing is set."""
1850df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offload_func = self._mock_get_offload_func(True, True)
1860df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offloader = gs_offloader.Offloader(_get_options(['-m']))
1870df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.assertEqual(offloader._offload_func,
1880df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang                         offload_func)
1890df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.mox.VerifyAll()
1900df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang
1910df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang    def test_offloader_multiprocessing_flag_not_set_default_false(self):
1920df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        """Test multiprocessing is set."""
1930df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        gs_offloader.GS_OFFLOADER_MULTIPROCESSING = False
1940df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offload_func = self._mock_get_offload_func(True, False)
1950df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offloader = gs_offloader.Offloader(_get_options([]))
1960df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.assertEqual(offloader._offload_func,
1970df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang                         offload_func)
1980df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.mox.VerifyAll()
1990df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang
2000df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang    def test_offloader_multiprocessing_flag_not_set_default_true(self):
2010df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        """Test multiprocessing is set."""
2020df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        gs_offloader.GS_OFFLOADER_MULTIPROCESSING = True
2030df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offload_func = self._mock_get_offload_func(True, True)
2040df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offloader = gs_offloader.Offloader(_get_options([]))
2050df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.assertEqual(offloader._offload_func,
2060df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang                         offload_func)
2070df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.mox.VerifyAll()
2080df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang
20997d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang    def test_offloader_pubsub_topic_not_set(self):
21097d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        """Test multiprocessing is set."""
21197d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        offload_func = self._mock_get_offload_func(True, False)
21297d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        offloader = gs_offloader.Offloader(_get_options([]))
21397d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.assertEqual(offloader._offload_func,
21497d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang                         offload_func)
21597d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.mox.VerifyAll()
21697d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
21797d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang    def test_offloader_pubsub_topic_set(self):
21897d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        """Test multiprocessing is set."""
21997d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        offload_func = self._mock_get_offload_func(True, False, 'test-topic')
22097d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        offloader = gs_offloader.Offloader(_get_options(['-t', 'test-topic']))
22197d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.assertEqual(offloader._offload_func,
22297d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang                         offload_func)
22397d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.mox.VerifyAll()
22497d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
225f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi
226ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnettedef _make_timestamp(age_limit, is_expired):
227ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Create a timestamp for use by `job_directories._is_job_expired()`.
228ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
229ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    The timestamp will meet the syntactic requirements for
230ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    timestamps used as input to `_is_job_expired()`.  If
231ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `is_expired` is true, the timestamp will be older than
232ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `age_limit` days before the current time; otherwise, the
233ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    date will be younger.
234ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
235ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    @param age_limit    The number of days before expiration of the
236ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        target timestamp.
237ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    @param is_expired   Whether the timestamp should be expired
238ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        relative to `age_limit`.
239ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
240ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
241ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    seconds = -_MARGIN_SECS
242ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    if is_expired:
243ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        seconds = -seconds
244ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    delta = datetime.timedelta(days=age_limit, seconds=seconds)
245ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    reference_time = datetime.datetime.now() - delta
246dfea368e5c830b1d7950ced5ee7b191e3b141ca3Dan Shi    return reference_time.strftime(time_utils.TIME_FMT)
247ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
248ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
249ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass JobExpirationTests(unittest.TestCase):
250ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests to exercise `job_directories._is_job_expired()`."""
251ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
252ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_expired(self):
253ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test detection of an expired job."""
254ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        timestamp = _make_timestamp(_TEST_EXPIRATION_AGE, True)
255ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(
256ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            job_directories._is_job_expired(
257ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                _TEST_EXPIRATION_AGE, timestamp))
258ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
259ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
260ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_alive(self):
261ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test detection of a job that's not expired."""
262ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # N.B.  This test may fail if its run time exceeds more than
263ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # about _MARGIN_SECS seconds.
264ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        timestamp = _make_timestamp(_TEST_EXPIRATION_AGE, False)
265ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(
266ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            job_directories._is_job_expired(
267ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                _TEST_EXPIRATION_AGE, timestamp))
268ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
269ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
270ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass _MockJobDirectory(job_directories._JobDirectory):
271ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Subclass of `_JobDirectory` used as a helper for tests."""
272ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
273ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    GLOB_PATTERN = '[0-9]*-*'
274ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
27524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
276ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def __init__(self, resultsdir):
277ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Create new job in initial state."""
278ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(_MockJobDirectory, self).__init__(resultsdir)
279ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._timestamp = None
2802c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        self.queue_args = [resultsdir, os.path.dirname(resultsdir)]
281ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
28224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
283ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def get_timestamp_if_finished(self):
284ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        return self._timestamp
285ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
28624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
287ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_finished(self, days_old):
288ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job appear to be finished.
289ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
290ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        After calling this function, calls to `enqueue_offload()`
291ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        will find this job as finished, but not expired and ready
292ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for offload.  Note that when `days_old` is 0,
293ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `enqueue_offload()` will treat a finished job as eligible
294ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for offload.
295ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
296ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param days_old The value of the `days_old` parameter that
297ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        will be passed to `enqueue_offload()` for
298ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        testing.
299ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
300ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
301ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._timestamp = _make_timestamp(days_old, False)
302ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
30324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
304ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_expired(self, days_old):
305ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job eligible to be offloaded.
306ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
307ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        After calling this function, calls to `offload` will attempt
308ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        to offload this job.
309ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
310ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param days_old The value of the `days_old` parameter that
311ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        will be passed to `enqueue_offload()` for
312ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        testing.
313ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
314ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
315ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._timestamp = _make_timestamp(days_old, True)
316ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
31724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
318ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_incomplete(self):
319ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job appear to have failed offload just once."""
320ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_count += 1
32122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._first_offload_start = time.time()
322ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        if not os.path.isdir(self._dirname):
323ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            os.mkdir(self._dirname)
324ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
32524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
326ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_reportable(self):
327ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job be reportable."""
328ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.set_incomplete()
32922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._offload_count += 1
330ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
33124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
332ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_complete(self):
333ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job be completed."""
334ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_count += 1
335ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        if os.path.isdir(self._dirname):
336ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            os.rmdir(self._dirname)
337ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
338ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
3391e10e92049f4b2724ea43186083e995e418f9802Simran Basi    def process_gs_instructions(self):
3401e10e92049f4b2724ea43186083e995e418f9802Simran Basi        """Always still offload the job directory."""
3411e10e92049f4b2724ea43186083e995e418f9802Simran Basi        return True
3421e10e92049f4b2724ea43186083e995e418f9802Simran Basi
3431e10e92049f4b2724ea43186083e995e418f9802Simran Basi
3449f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnetteclass CommandListTests(unittest.TestCase):
3459f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette    """Tests for `get_cmd_list()`."""
3469f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
347e93c85778aa8b22aa88482c43092133d59434147MK Ryu    def _command_list_assertions(self, job, use_rsync=True, multi=False):
3489f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        """Call `get_cmd_list()` and check the return value.
3499f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3509f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        Check the following assertions:
3519f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette          * The command name (argv[0]) is 'gsutil'.
352e93c85778aa8b22aa88482c43092133d59434147MK Ryu          * '-m' option (argv[1]) is on when the argument, multi, is True.
3539f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette          * The arguments contain the 'cp' subcommand.
3549f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette          * The next-to-last argument (the source directory) is the
3559f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette            job's `queue_args[0]`.
356dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi          * The last argument (the destination URL) is the job's
357dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi            'queue_args[1]'.
3589f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3599f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        @param job A job with properly calculated arguments to
3609f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette                   `get_cmd_list()`
361e93c85778aa8b22aa88482c43092133d59434147MK Ryu        @param use_rsync True when using 'rsync'. False when using 'cp'.
362e93c85778aa8b22aa88482c43092133d59434147MK Ryu        @param multi True when using '-m' option for gsutil.
3639f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3649f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        """
36524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        test_bucket_uri = 'gs://a-test-bucket'
36624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
36724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        gs_offloader.USE_RSYNC_ENABLED = use_rsync
36824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
36924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        command = gs_offloader.get_cmd_list(
370e93c85778aa8b22aa88482c43092133d59434147MK Ryu                multi, job.queue_args[0],
371e93c85778aa8b22aa88482c43092133d59434147MK Ryu                os.path.join(test_bucket_uri, job.queue_args[1]))
37224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
3739f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self.assertEqual(command[0], 'gsutil')
374e93c85778aa8b22aa88482c43092133d59434147MK Ryu        if multi:
375e93c85778aa8b22aa88482c43092133d59434147MK Ryu            self.assertEqual(command[1], '-m')
3769f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self.assertEqual(command[-2], job.queue_args[0])
37724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
37824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        if use_rsync:
37924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertTrue('rsync' in command)
38024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertEqual(command[-1],
38124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich                             os.path.join(test_bucket_uri, job.queue_args[0]))
38224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        else:
38324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertTrue('cp' in command)
38424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertEqual(command[-1],
38524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich                             os.path.join(test_bucket_uri, job.queue_args[1]))
38624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
3879f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3889f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette    def test_get_cmd_list_regular(self):
3899f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        """Test `get_cmd_list()` as for a regular job."""
3909f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        job = _MockJobDirectory('118-debug')
3919f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self._command_list_assertions(job)
3929f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
39324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
3949f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette    def test_get_cmd_list_special(self):
3959f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        """Test `get_cmd_list()` as for a special job."""
3969f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        job = _MockJobDirectory('hosts/host1/118-reset')
3979f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self._command_list_assertions(job)
3989f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3999f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
40024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich    def test_get_cmd_list_regular_no_rsync(self):
40124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        """Test `get_cmd_list()` as for a regular job."""
40224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        job = _MockJobDirectory('118-debug')
40324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        self._command_list_assertions(job, use_rsync=False)
40424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
40524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
40624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich    def test_get_cmd_list_special_no_rsync(self):
40724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        """Test `get_cmd_list()` as for a special job."""
40824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        job = _MockJobDirectory('hosts/host1/118-reset')
40924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        self._command_list_assertions(job, use_rsync=False)
41024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
41124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
412e93c85778aa8b22aa88482c43092133d59434147MK Ryu    def test_get_cmd_list_regular_multi(self):
413e93c85778aa8b22aa88482c43092133d59434147MK Ryu        """Test `get_cmd_list()` as for a regular job with True multi."""
414e93c85778aa8b22aa88482c43092133d59434147MK Ryu        job = _MockJobDirectory('118-debug')
415e93c85778aa8b22aa88482c43092133d59434147MK Ryu        self._command_list_assertions(job, multi=True)
416e93c85778aa8b22aa88482c43092133d59434147MK Ryu
417e93c85778aa8b22aa88482c43092133d59434147MK Ryu
418e93c85778aa8b22aa88482c43092133d59434147MK Ryu    def test_get_cmd_list_special_multi(self):
419e93c85778aa8b22aa88482c43092133d59434147MK Ryu        """Test `get_cmd_list()` as for a special job with True multi."""
420e93c85778aa8b22aa88482c43092133d59434147MK Ryu        job = _MockJobDirectory('hosts/host1/118-reset')
421e93c85778aa8b22aa88482c43092133d59434147MK Ryu        self._command_list_assertions(job, multi=True)
422e93c85778aa8b22aa88482c43092133d59434147MK Ryu
423e93c85778aa8b22aa88482c43092133d59434147MK Ryu
424ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# Below is partial sample of e-mail notification text.  This text is
425ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# deliberately hard-coded and then parsed to create the test data;
426ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# the idea is to make sure the actual text format will be reviewed
427ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# by a human being.
428ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette#
429ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# first offload      count  directory
430ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# --+----1----+----  ----+  ----+----1----+----2----+----3
431ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette_SAMPLE_DIRECTORIES_REPORT = '''\
432ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette=================== ======  ==============================
433ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette2014-03-14 15:09:26      1  118-fubar
434ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette2014-03-14 15:19:23      2  117-fubar
435ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette2014-03-14 15:29:20      6  116-fubar
436ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette2014-03-14 15:39:17     24  115-fubar
437ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette2014-03-14 15:49:14    120  114-fubar
438ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette2014-03-14 15:59:11    720  113-fubar
439ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette2014-03-14 16:09:08   5040  112-fubar
440ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette2014-03-14 16:19:05  40320  111-fubar
441ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette'''
442ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
443ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
444ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass EmailTemplateTests(mox.MoxTestBase):
445ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Test the formatting of e-mail notifications."""
446ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
447ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
448ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(EmailTemplateTests, self).setUp()
449ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.StubOutWithMock(email_manager.manager,
450ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                                 'send_email')
451ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._joblist = []
452ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for line in _SAMPLE_DIRECTORIES_REPORT.split('\n')[1 : -1]:
453ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            date_, time_, count, dir_ = line.split()
454ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            job = _MockJobDirectory(dir_)
455ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            job._offload_count = int(count)
456dfea368e5c830b1d7950ced5ee7b191e3b141ca3Dan Shi            timestruct = time.strptime("%s %s" % (date_, time_),
457dfea368e5c830b1d7950ced5ee7b191e3b141ca3Dan Shi                                       gs_offloader.ERROR_EMAIL_TIME_FORMAT)
458ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            job._first_offload_start = time.mktime(timestruct)
459ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            # enter the jobs in reverse order, to make sure we
460ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            # test that the output will be sorted.
461ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._joblist.insert(0, job)
462ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
46324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
464ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_email_template(self):
465ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Trigger an e-mail report and check its contents."""
466ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # The last line of the report is a separator that we
467ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # repeat in the first line of our expected result data.
468ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # So, we remove that separator from the end of the of
469ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # the e-mail report message.
470ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        #
471ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # The last element in the list returned by split('\n')
472ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # will be an empty string, so to remove the separator,
473ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # we remove the next-to-last entry in the list.
474ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        report_lines = gs_offloader.ERROR_EMAIL_REPORT_FORMAT.split('\n')
475ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        expected_message = ('\n'.join(report_lines[: -2] +
476ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                                      report_lines[-1 :]) +
477ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                            _SAMPLE_DIRECTORIES_REPORT)
478ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        email_manager.manager.send_email(
479ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            mox.IgnoreArg(), mox.IgnoreArg(), expected_message)
480ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ReplayAll()
481ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        gs_offloader.report_offload_failures(self._joblist)
482ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
483ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
484686ae8c339d31988e07bde0ab5d7b3731c0570f1Kevin Cheng    def test_email_url(self):
485686ae8c339d31988e07bde0ab5d7b3731c0570f1Kevin Cheng        """Check that the expected helper url is in the email header."""
486686ae8c339d31988e07bde0ab5d7b3731c0570f1Kevin Cheng        self.assertIn(gs_offloader.ERROR_EMAIL_HELPER_URL,
487686ae8c339d31988e07bde0ab5d7b3731c0570f1Kevin Cheng                      gs_offloader.ERROR_EMAIL_REPORT_FORMAT)
488686ae8c339d31988e07bde0ab5d7b3731c0570f1Kevin Cheng
489686ae8c339d31988e07bde0ab5d7b3731c0570f1Kevin Cheng
49097d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tangclass PubSubTest(mox.MoxTestBase):
49197d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang    """Test the test result notifcation data structure."""
49297d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
49397d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang    def test_create_test_result_notification(self):
49497d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        """Tests the test result notification message."""
49597d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        msg = gs_offloader._create_test_result_notification('gs://test_bucket')
49697d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.assertEquals(base64.b64encode(
49797d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang            gs_offloader.NEW_TEST_RESULT_MESSAGE), msg['data'])
49897d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.assertEquals('gs://test_bucket', msg['attributes']['gcs_uri'])
49997d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
50097d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
501dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnetteclass _MockJob(object):
502dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    """Class to mock the return value of `AFE.get_jobs()`."""
503dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def __init__(self, created):
504dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.created_on = created
505dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
506dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
507dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnetteclass _MockHostQueueEntry(object):
508dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    """Class to mock the return value of `AFE.get_host_queue_entries()`."""
509dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def __init__(self, finished):
510dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.finished_on = finished
511dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
512dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
513dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnetteclass _MockSpecialTask(object):
514dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    """Class to mock the return value of `AFE.get_special_tasks()`."""
515dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def __init__(self, finished):
516dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.time_finished = finished
517dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
518dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
5192c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnetteclass JobDirectorySubclassTests(mox.MoxTestBase):
5202c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette    """Test specific to RegularJobDirectory and SpecialJobDirectory.
5213e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
5223e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    This provides coverage for the implementation in both
5233e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    RegularJobDirectory and SpecialJobDirectory.
5243e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
5253e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    """
5263e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
5273e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def setUp(self):
5282c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        super(JobDirectorySubclassTests, self).setUp()
529dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.StubOutWithMock(job_directories._AFE, 'get_jobs')
530dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.StubOutWithMock(job_directories._AFE,
531dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 'get_host_queue_entries')
532dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.StubOutWithMock(job_directories._AFE,
533dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 'get_special_tasks')
5343e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
53524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
5362c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette    def test_regular_job_fields(self):
5372c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """Test the constructor for `RegularJobDirectory`.
5382c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5392c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        Construct a regular job, and assert that the `_dirname`
5402c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        and `_id` attributes are set as expected.
5412c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5422c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """
5432c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        resultsdir = '118-fubar'
5442c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.RegularJobDirectory(resultsdir)
5452c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        self.assertEqual(job._dirname, resultsdir)
546cf4d2032ea4bf5af680383f36308d581876bbbb0Dan Shi        self.assertEqual(job._id, 118)
5472c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
54824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
5492c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette    def test_special_job_fields(self):
5502c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """Test the constructor for `SpecialJobDirectory`.
5512c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5522c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        Construct a special job, and assert that the `_dirname`
5532c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        and `_id` attributes are set as expected.
5542c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5552c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """
5562c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        destdir = 'hosts/host1'
5572c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        resultsdir = destdir + '/118-reset'
5582c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.SpecialJobDirectory(resultsdir)
5592c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        self.assertEqual(job._dirname, resultsdir)
560cf4d2032ea4bf5af680383f36308d581876bbbb0Dan Shi        self.assertEqual(job._id, 118)
5612c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
56224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
563dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def _check_finished_job(self, jobtime, hqetimes, expected):
564dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        """Mock and test behavior of a finished job.
565dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
566dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        Initialize the mocks for a call to
567dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        `get_timestamp_if_finished()`, then simulate one call.
568dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        Assert that the returned timestamp matches the passed
569dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        in expected value.
570dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
571dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        @param jobtime Time used to construct a _MockJob object.
572dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        @param hqetimes List of times used to construct
573dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        _MockHostQueueEntry objects.
574dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        @param expected Expected time to be returned by
575dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        get_timestamp_if_finished
576dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
577dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        """
578dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job = job_directories.RegularJobDirectory('118-fubar')
579dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_jobs(
580dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, finished=True).AndReturn(
581dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        [_MockJob(jobtime)])
582dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_host_queue_entries(
583dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                finished_on__isnull=False,
584dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                job_id=job._id).AndReturn(
585dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        [_MockHostQueueEntry(t) for t in hqetimes])
586dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.ReplayAll()
587dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.assertEqual(expected, job.get_timestamp_if_finished())
588dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
589dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
590dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
5913e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_finished_regular_job(self):
5923e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for a finished regular job.
5933e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
5943e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
5953e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `RegularJobDirectory.get_timestamp_if_finished()` when
5963e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is finished.
5973e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
5983e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
599dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        created_timestamp = _make_timestamp(1, True)
600dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        hqe_timestamp = _make_timestamp(0, True)
601dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(created_timestamp,
602dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 [hqe_timestamp],
603dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 hqe_timestamp)
604fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
60524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
606fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi    def test_finished_regular_job_multiple_hqes(self):
607fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """Test getting the timestamp for a regular job with multiple hqes.
608fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
609fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        Tests the return value for
610fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        `RegularJobDirectory.get_timestamp_if_finished()` when
611fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        the AFE indicates the job is finished and the job has multiple host
612fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        queue entries.
613fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
614dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        Tests that the returned timestamp is the latest timestamp in
615dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        the list of HQEs, regardless of the returned order.
616dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
617fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """
618fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        created_timestamp = _make_timestamp(2, True)
619fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        older_hqe_timestamp = _make_timestamp(1, True)
620fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        newer_hqe_timestamp = _make_timestamp(0, True)
621dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        hqe_list = [older_hqe_timestamp,
622dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                    newer_hqe_timestamp]
623dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(created_timestamp,
624dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 hqe_list,
625dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 newer_hqe_timestamp)
626dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.ResetAll()
627dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        hqe_list.reverse()
628dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(created_timestamp,
629dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 hqe_list,
630dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 newer_hqe_timestamp)
631fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
63224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
633fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi    def test_finished_regular_job_null_finished_times(self):
634fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """Test getting the timestamp for an aborted regular job.
635fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
636fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        Tests the return value for
637fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        `RegularJobDirectory.get_timestamp_if_finished()` when
638fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        the AFE indicates the job is finished and the job has aborted host
639fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        queue entries.
640fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
641fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """
642fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        timestamp = _make_timestamp(0, True)
643dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(timestamp, [], timestamp)
6443e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
64524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6463e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_unfinished_regular_job(self):
6473e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for an unfinished regular job.
6483e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6493e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
6503e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `RegularJobDirectory.get_timestamp_if_finished()` when
6513e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is not finished.
6523e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6533e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
6543e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        job = job_directories.RegularJobDirectory('118-fubar')
655dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_jobs(
656dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, finished=True).AndReturn([])
6573e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.mox.ReplayAll()
6583e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.assertIsNone(job.get_timestamp_if_finished())
659dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
6603e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
66124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6623e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_finished_special_job(self):
6633e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for a finished special job.
6643e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6653e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
6663e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `SpecialJobDirectory.get_timestamp_if_finished()` when
6673e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is finished.
6683e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6693e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
6702c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.SpecialJobDirectory(
6712c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette                'hosts/host1/118-reset')
6723e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        timestamp = _make_timestamp(0, True)
673dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_special_tasks(
674dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, is_complete=True).AndReturn(
675dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                    [_MockSpecialTask(timestamp)])
6763e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.mox.ReplayAll()
6773e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.assertEqual(timestamp,
6783e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette                         job.get_timestamp_if_finished())
679dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
6803e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
68124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6823e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_unfinished_special_job(self):
6833e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for an unfinished special job.
6843e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6853e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
6863e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `SpecialJobDirectory.get_timestamp_if_finished()` when
6873e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is not finished.
6883e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6893e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
6902c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.SpecialJobDirectory(
6912c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette                'hosts/host1/118-reset')
692dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_special_tasks(
693dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, is_complete=True).AndReturn([])
6943e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.mox.ReplayAll()
6953e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.assertIsNone(job.get_timestamp_if_finished())
696dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
6973e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6983e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
699ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass _TempResultsDirTestBase(mox.MoxTestBase):
700ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Base class for tests using a temporary results directory."""
701ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
7020880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    REGULAR_JOBLIST = [
7030880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        '111-fubar', '112-fubar', '113-fubar', '114-snafu']
7040880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    HOST_LIST = ['host1', 'host2', 'host3']
7050880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    SPECIAL_JOBLIST = [
7060880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        'hosts/host1/333-reset', 'hosts/host1/334-reset',
7070880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        'hosts/host2/444-reset', 'hosts/host3/555-reset']
7080880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
70924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
710ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
711ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(_TempResultsDirTestBase, self).setUp()
7120880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._resultsroot = tempfile.mkdtemp()
7130880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._cwd = os.getcwd()
7140880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.chdir(self._resultsroot)
715ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
71624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
717ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def tearDown(self):
7180880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.chdir(self._cwd)
719ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        shutil.rmtree(self._resultsroot)
720ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(_TempResultsDirTestBase, self).tearDown()
721ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
72224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
723ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def make_job(self, jobdir):
724ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Create a job with results in `self._resultsroot`.
725ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
726ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param jobdir Name of the subdirectory to be created in
727ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                      `self._resultsroot`.
728ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
729ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
7300880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.mkdir(jobdir)
7310880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        return _MockJobDirectory(jobdir)
7320880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
73324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
7340880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    def make_job_hierarchy(self):
7350880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        """Create a sample hierarchy of job directories.
7360880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
7370880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        `self.REGULAR_JOBLIST` is a list of directories for regular
7380880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        jobs to be created; `self.SPECIAL_JOBLIST` is a list of
7390880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        directories for special jobs to be created.
7400880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
7410880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        """
7420880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
7430880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(d)
7440880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        hostsdir = 'hosts'
7450880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.mkdir(hostsdir)
7460880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for host in self.HOST_LIST:
7470880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(os.path.join(hostsdir, host))
7480880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.SPECIAL_JOBLIST:
7490880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(d)
750ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
751ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
7522e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnetteclass OffloadDirectoryTests(_TempResultsDirTestBase):
7532e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    """Tests for `offload_dir()`."""
7542e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
7552e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def setUp(self):
7562e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        super(OffloadDirectoryTests, self).setUp()
7572e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        # offload_dir() logs messages; silence them.
7582e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._saved_loglevel = logging.getLogger().getEffectiveLevel()
7592e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        logging.getLogger().setLevel(logging.CRITICAL+1)
7602e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._job = self.make_job(self.REGULAR_JOBLIST[0])
7612e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.StubOutWithMock(gs_offloader, 'get_cmd_list')
7622e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.StubOutWithMock(signal, 'alarm')
7632d981eee42e4f9fb4f6d726b97aa8122322543beNingning Xia        self.mox.StubOutWithMock(models.test, 'parse_job_keyval')
7642e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
76524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
7662e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def tearDown(self):
7672e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        logging.getLogger().setLevel(self._saved_loglevel)
7682e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        super(OffloadDirectoryTests, self).tearDown()
7692e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
7704211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia    def _mock_upload_testresult_files(self):
7714211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self.mox.StubOutWithMock(gs_offloader, 'upload_testresult_files')
7724211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        gs_offloader.upload_testresult_files(
7734211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia                mox.IgnoreArg(),mox.IgnoreArg()).AndReturn(None)
77424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
775dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi    def _mock_offload_dir_calls(self, command, queue_args):
7762e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Mock out the calls needed by `offload_dir()`.
7772e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
7782e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        This covers only the calls made when there is no timeout.
7792e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
7802e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        @param command Command list to be returned by the mocked
7812e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                       call to `get_cmd_list()`.
7822e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
7832e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
7842e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(gs_offloader.OFFLOAD_TIMEOUT_SECS)
785dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        command.append(queue_args[0])
7862e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        gs_offloader.get_cmd_list(
787e93c85778aa8b22aa88482c43092133d59434147MK Ryu                False, queue_args[0],
788e93c85778aa8b22aa88482c43092133d59434147MK Ryu                '%s%s' % (utils.DEFAULT_OFFLOAD_GSURI,
789e93c85778aa8b22aa88482c43092133d59434147MK Ryu                          queue_args[1])).AndReturn(command)
7904211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self._mock_upload_testresult_files()
7912e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0)
7922e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0)
7932e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
79424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
7952e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def _run_offload_dir(self, should_succeed):
7962e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Make one call to `offload_dir()`.
7972e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
7982e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        The caller ensures all mocks are set up already.
7992e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8002e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        @param should_succeed True iff the call to `offload_dir()`
8012e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                              is expected to succeed and remove the
8022e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                              offloaded job directory.
8032e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8042e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
8052e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.ReplayAll()
806dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        gs_offloader.get_offload_dir_func(
807e93c85778aa8b22aa88482c43092133d59434147MK Ryu                utils.DEFAULT_OFFLOAD_GSURI, False)(
808e93c85778aa8b22aa88482c43092133d59434147MK Ryu                        self._job.queue_args[0],
809e93c85778aa8b22aa88482c43092133d59434147MK Ryu                        self._job.queue_args[1])
8102e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.VerifyAll()
8112e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.assertEqual(not should_succeed,
8122e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                         os.path.isdir(self._job.queue_args[0]))
8132e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
81424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8152e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_success(self):
8162e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` can succeed correctly."""
817dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self._mock_offload_dir_calls(['test', '-d'],
818dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                                     self._job.queue_args)
8192e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._run_offload_dir(True)
8202e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
82124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8222e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_failure(self):
8232e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` can fail correctly."""
824dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self._mock_offload_dir_calls(['test', '!', '-d'],
825dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                                     self._job.queue_args)
8262e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._run_offload_dir(False)
8272e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
82824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8292e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_timeout_early(self):
8302e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` times out correctly.
8312e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8322e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        This test triggers timeout at the earliest possible moment,
8332e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        at the first call to set the timeout alarm.
8342e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8352e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
8364211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self._mock_upload_testresult_files()
8372e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(gs_offloader.OFFLOAD_TIMEOUT_SECS).AndRaise(
8382e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                        gs_offloader.TimeoutException('fubar'))
8392e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0)
8402e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._run_offload_dir(False)
8412e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
84224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8432e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_timeout_late(self):
8442e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` times out correctly.
8452e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8462e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        This test triggers timeout at the latest possible moment, at
8472e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        the call to clear the timeout alarm.
8482e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8492e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
8502e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(gs_offloader.OFFLOAD_TIMEOUT_SECS)
8512e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        gs_offloader.get_cmd_list(
852e93c85778aa8b22aa88482c43092133d59434147MK Ryu                False, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
8532e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                        ['test', '-d', self._job.queue_args[0]])
8544211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self._mock_upload_testresult_files()
8552e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0).AndRaise(
8562e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                gs_offloader.TimeoutException('fubar'))
8572e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        signal.alarm(0)
8582e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._run_offload_dir(False)
8592e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8602e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
861affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi    def test_sanitize_dir(self):
862affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        """Test that folder/file name with invalid character can be corrected.
863affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        """
864affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        results_folder = tempfile.mkdtemp()
865affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_chars = '_'.join(gs_offloader.INVALID_GS_CHARS)
866affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_files = []
867affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_folder = os.path.join(
868affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                results_folder,
869affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                'invalid_name_folder_%s' % invalid_chars)
870affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_files.append(os.path.join(
871affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                invalid_folder,
872affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                'invalid_name_file_%s' % invalid_chars))
873affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for r in gs_offloader.INVALID_GS_CHAR_RANGE:
874affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            for c in range(r[0], r[1]+1):
875affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                # NULL cannot be in file name.
876affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                if c != 0:
877affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                    invalid_files.append(os.path.join(
878affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                            invalid_folder,
879affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                            'invalid_name_file_%s' % chr(c)))
880affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        good_folder =  os.path.join(results_folder, 'valid_name_folder')
881affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        good_file = os.path.join(good_folder, 'valid_name_file')
882affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for folder in [invalid_folder, good_folder]:
883affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            os.makedirs(folder)
884affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for f in invalid_files + [good_file]:
885affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            with open(f, 'w'):
886affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                pass
887affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        gs_offloader.sanitize_dir(results_folder)
888affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for _, dirs, files in os.walk(results_folder):
889affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            for name in dirs + files:
890affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                self.assertEqual(name, gs_offloader.get_sanitized_name(name))
891affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                for c in name:
892affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                    self.assertFalse(c in gs_offloader.INVALID_GS_CHARS)
893affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                    for r in gs_offloader.INVALID_GS_CHAR_RANGE:
894affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                        self.assertFalse(ord(c) >= r[0] and ord(c) <= r[1])
895affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        self.assertTrue(os.path.exists(good_file))
896affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        shutil.rmtree(results_folder)
897affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi
898affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi
8991b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi    def check_limit_file_count(self, is_test_job=True):
9001b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """Test that folder with too many files can be compressed.
9011b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9021b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        @param is_test_job: True to check the method with test job result
9031b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                            folder. Set to False for special task folder.
9041b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """
9051b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        results_folder = tempfile.mkdtemp()
9061b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        host_folder = os.path.join(
9071b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                results_folder,
9081b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                'lab1-host1' if is_test_job else 'hosts/lab1-host1/1-repair')
9091b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        debug_folder = os.path.join(host_folder, 'debug')
9101b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        sysinfo_folder = os.path.join(host_folder, 'sysinfo')
9111b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        for folder in [debug_folder, sysinfo_folder]:
9121b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi            os.makedirs(folder)
9131b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi            for i in range(10):
9141b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                with open(os.path.join(folder, str(i)), 'w') as f:
9151b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                    f.write('test')
9161b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9171b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.MAX_FILE_COUNT = 100
9181b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.limit_file_count(
9191b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                results_folder if is_test_job else host_folder)
9201b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertTrue(os.path.exists(sysinfo_folder))
9211b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9221b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.MAX_FILE_COUNT = 10
9231b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.limit_file_count(
9241b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                results_folder if is_test_job else host_folder)
9251b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertFalse(os.path.exists(sysinfo_folder))
9261b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertTrue(os.path.exists(sysinfo_folder + '.tgz'))
9271b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertTrue(os.path.exists(debug_folder))
9281b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9291b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        shutil.rmtree(results_folder)
9301b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9311b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9321b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi    def test_limit_file_count(self):
9331b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """Test that folder with too many files can be compressed.
9341b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """
9351b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.check_limit_file_count(is_test_job=True)
9361b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.check_limit_file_count(is_test_job=False)
9371b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9382d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
9398db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia    def test_is_valid_result(self):
9408db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        """Test _is_valid_result."""
94121922c807733cab1a86096500304aa8ae68bd897Ningning Xia        release_build = 'veyron_minnie-cheets-release/R52-8248.0.0'
94221922c807733cab1a86096500304aa8ae68bd897Ningning Xia        pfq_build = 'cyan-cheets-android-pfq/R54-8623.0.0-rc1'
94321922c807733cab1a86096500304aa8ae68bd897Ningning Xia        trybot_build = 'trybot-samus-release/R54-8640.0.0-b5092'
94421922c807733cab1a86096500304aa8ae68bd897Ningning Xia        trybot_2_build = 'trybot-samus-pfq/R54-8640.0.0-b5092'
94521922c807733cab1a86096500304aa8ae68bd897Ningning Xia        release_2_build = 'test-trybot-release/R54-8640.0.0-b5092'
9468db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertTrue(gs_offloader._is_valid_result(
9478db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
9486384c1094ddf148de5d3ff16aed1bbab077b5f26Rohit Makasana        self.assertTrue(gs_offloader._is_valid_result(
9496384c1094ddf148de5d3ff16aed1bbab077b5f26Rohit Makasana            release_build, gs_offloader.CTS_RESULT_PATTERN, 'test_that_wrapper'))
9508db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
9518db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-bvt-cq'))
9528db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertTrue(gs_offloader._is_valid_result(
9538db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.GTS_RESULT_PATTERN, 'arc-gts-tot'))
9548db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
9558db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            None, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
9568db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
9578db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.CTS_RESULT_PATTERN, None))
9588db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
9598db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            pfq_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
9608db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
9618db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            trybot_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
9628db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
9638db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            trybot_2_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
9648db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertTrue(gs_offloader._is_valid_result(
9658db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_2_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
96621922c807733cab1a86096500304aa8ae68bd897Ningning Xia
96721922c807733cab1a86096500304aa8ae68bd897Ningning Xia
9680c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia    def create_results_folder(self):
9690c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        """Create CTS/GTS results folders."""
9704211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        results_folder = tempfile.mkdtemp()
9714211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        host_folder = os.path.join(results_folder, 'chromeos4-row9-rack11-host22')
9724211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        debug_folder = os.path.join(host_folder, 'debug')
9734211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        sysinfo_folder = os.path.join(host_folder, 'sysinfo')
9744211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        cts_result_folder = os.path.join(
9754211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia                host_folder, 'cheets_CTS.android.dpi', 'results', 'cts-results')
9762d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        gts_result_folder = os.path.join(
9772d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia                host_folder, 'cheets_GTS.google.admin', 'results', 'android-xts')
9784211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        timestamp_str = '2016.04.28_01.41.44'
9792d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        timestamp_cts_folder = os.path.join(cts_result_folder, timestamp_str)
9802d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        timestamp_gts_folder = os.path.join(gts_result_folder, timestamp_str)
9812d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
9820c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        # Test results in cts_result_folder with a different time-stamp.
9830c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        timestamp_str_2 = '2016.04.28_10.41.44'
9840c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        timestamp_cts_folder_2 = os.path.join(cts_result_folder, timestamp_str_2)
9850c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
9862d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        for folder in [debug_folder, sysinfo_folder, cts_result_folder,
9870c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                       timestamp_cts_folder, timestamp_gts_folder, timestamp_cts_folder_2]:
9884211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia            os.makedirs(folder)
9892d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
9900c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        path_pattern_pair = [(timestamp_cts_folder, gs_offloader.CTS_RESULT_PATTERN),
9910c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                             (timestamp_cts_folder_2, gs_offloader.CTS_RESULT_PATTERN),
9920c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                             (timestamp_gts_folder, gs_offloader.GTS_RESULT_PATTERN)]
9934211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
9940c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        # Create timestamp.zip file_path.
9950c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_zip_file = os.path.join(cts_result_folder, timestamp_str + '.zip')
9960c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_zip_file_2 = os.path.join(cts_result_folder, timestamp_str_2 + '.zip')
9972d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        gts_zip_file = os.path.join(gts_result_folder, timestamp_str + '.zip')
9984211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
9990c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        # Create xml file_path.
10000c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_result_file = os.path.join(timestamp_cts_folder, 'testResult.xml')
10010c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_result_file_2 = os.path.join(timestamp_cts_folder_2, 'testResult.xml')
10022d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        gts_result_file = os.path.join(timestamp_gts_folder, 'xtsTestResult.xml')
10032d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10040c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        for file_path in [cts_zip_file, cts_zip_file_2, gts_zip_file,
10050c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                          cts_result_file, cts_result_file_2, gts_result_file]:
10060c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            with open(file_path, 'w') as f:
10070c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                f.write('test')
10082d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10090c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        return (results_folder, host_folder, path_pattern_pair)
10102d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10110c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10120c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia    def test_upload_testresult_files(self):
10130c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        """Test upload_testresult_files."""
10140c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        results_folder, host_folder, path_pattern_pair = self.create_results_folder()
10150c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10160c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        self.mox.StubOutWithMock(gs_offloader, '_upload_files')
10170c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        gs_offloader._upload_files(
10180c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn(
10190c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                ['test', '-d', host_folder])
10200c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        gs_offloader._upload_files(
10210c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn(
10220c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                ['test', '-d', host_folder])
10230c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        gs_offloader._upload_files(
10240c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn(
10250c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                ['test', '-d', host_folder])
10264211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
10274211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self.mox.ReplayAll()
10284211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        gs_offloader.upload_testresult_files(results_folder, False)
10294211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self.mox.VerifyAll()
10300c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        shutil.rmtree(results_folder)
10310c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10320c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10330c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia    def test_upload_files(self):
10340c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        """Test upload_files"""
10350c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        results_folder, host_folder, path_pattern_pair = self.create_results_folder()
10360c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10370c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        for path, pattern in path_pattern_pair:
10380c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            models.test.parse_job_keyval(mox.IgnoreArg()).AndReturn({
10390c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                'build': 'veyron_minnie-cheets-release/R52-8248.0.0',
10408db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia                'parent_job_id': 'p_id',
10418db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia                'suite': 'arc-cts'
10420c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            })
10430c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10440c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            gs_offloader.get_cmd_list(
10450c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                False, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
10460c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                    ['test', '-d', path])
10470c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            gs_offloader.get_cmd_list(
10480c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                False, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
10490c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                    ['test', '-d', path])
10500c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10510c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            self.mox.ReplayAll()
10520c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            gs_offloader._upload_files(host_folder, path, pattern, False)
10530c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            self.mox.VerifyAll()
10540c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            self.mox.ResetAll()
10554211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
10564211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        shutil.rmtree(results_folder)
10571b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
105897d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
1059ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass JobDirectoryOffloadTests(_TempResultsDirTestBase):
1060ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `_JobDirectory.enqueue_offload()`.
1061ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1062ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    When testing with a `days_old` parameter of 0, we use
1063ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `set_finished()` instead of `set_expired()`.  This causes the
1064ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    job's timestamp to be set in the future.  This is done so as
1065ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    to test that when `days_old` is 0, the job is always treated
1066ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    as eligible for offload, regardless of the timestamp's value.
1067ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1068ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    Testing covers the following assertions:
1069ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     A. Each time `enqueue_offload()` is called, a message that
1070ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        includes the job's directory name will be logged using
1071ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `logging.debug()`, regardless of whether the job was
1072ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        enqueued.  Nothing else is allowed to be logged.
1073ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     B. If the job is not eligible to be offloaded,
107422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        `get_failure_time()` and `get_failure_count()` are 0.
1075ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     C. If the job is not eligible for offload, nothing is
1076ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        enqueued in `queue`.
107722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette     D. When the job is offloaded, `get_failure_count()` increments
1078ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        each time.
1079ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     E. When the job is offloaded, the appropriate parameters are
1080ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        enqueued exactly once.
108122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette     F. The first time a job is offloaded, `get_failure_time()` is
1082ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        set to the current time.
108322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette     G. `get_failure_time()` only changes the first time that the
1084ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job is offloaded.
1085ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1086ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    The test cases below are designed to exercise all of the
1087ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    meaningful state transitions at least once.
1088ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1089ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
1090ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1091ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1092ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(JobDirectoryOffloadTests, self).setUp()
10930880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._job = self.make_job(self.REGULAR_JOBLIST[0])
1094ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._queue = Queue.Queue()
1095ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
109624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1097ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _offload_unexpired_job(self, days_old):
1098ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make calls to `enqueue_offload()` for an unexpired job.
1099ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1100ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This method tests assertions B and C that calling
1101ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `enqueue_offload()` has no effect.
1102ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1103ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
110422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_count(), 0)
110522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_time(), 0)
110622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._job.enqueue_offload(self._queue, days_old)
110722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._job.enqueue_offload(self._queue, days_old)
1108ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(self._queue.empty())
110922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_count(), 0)
111022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_time(), 0)
111122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertFalse(self._job.is_reportable())
1112ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
111324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1114ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _offload_expired_once(self, days_old, count):
1115ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make one call to `enqueue_offload()` for an expired job.
1116ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1117ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This method tests assertions D and E regarding side-effects
1118ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        expected when a job is offloaded.
1119ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1120ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
112122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._job.enqueue_offload(self._queue, days_old)
112222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_count(), count)
1123ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(self._queue.empty())
1124ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        v = self._queue.get_nowait()
1125ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(self._queue.empty())
11262c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        self.assertEqual(v, self._job.queue_args)
1127ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
112824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1129ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _offload_expired_job(self, days_old):
1130ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make calls to `enqueue_offload()` for a just-expired job.
1131ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1132ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This method directly tests assertions F and G regarding
113322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        side-effects on `get_failure_time()`.
1134ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1135ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1136ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        t0 = time.time()
1137ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_once(days_old, 1)
113822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertFalse(self._job.is_reportable())
113922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        t1 = self._job.get_failure_time()
1140ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertLessEqual(t1, time.time())
1141ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertGreaterEqual(t1, t0)
1142ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_once(days_old, 2)
114322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertTrue(self._job.is_reportable())
114422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_time(), t1)
1145ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_once(days_old, 3)
114622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertTrue(self._job.is_reportable())
114722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.assertEqual(self._job.get_failure_time(), t1)
1148ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
114924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1150ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_1_no_expiration(self):
1151ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` of 0.
1152ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1153ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are
1154ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        made both before and after the job becomes expired.
1155ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1156ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1157ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(0)
1158ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(0)
1159ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(0)
1160ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
116124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1162ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_2_no_expiration(self):
1163ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` of 0.
1164ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1165ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1166ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only after the job becomes expired.
1167ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1168ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1169ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(0)
1170ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(0)
1171ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
117224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1173ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_1_with_expiration(self):
1174ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1175ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1176ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1177ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        before the job finishes, before the job expires, and after
1178ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the job expires.
1179ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1180ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1181ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1182ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(_TEST_EXPIRATION_AGE)
1183ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1184ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1185ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1186ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
118724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1188ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_2_with_expiration(self):
1189ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1190ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1191ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1192ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        between finishing and expiration, and after the job expires.
1193ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1194ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1195ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(_TEST_EXPIRATION_AGE)
1196ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1197ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1198ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1199ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
120024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1201ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_3_with_expiration(self):
1202ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1203ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1204ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1205ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only before finishing and after expiration.
1206ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1207ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1208ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1209ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1210ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1211ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
121224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1213ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_4_with_expiration(self):
1214ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1215ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1216ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1217ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only after expiration.
1218ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1219ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1220ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1221ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1222ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1223ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1224ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass GetJobDirectoriesTests(_TempResultsDirTestBase):
1225ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `_JobDirectory.get_job_directories()`."""
1226ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1227ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1228ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(GetJobDirectoriesTests, self).setUp()
12290880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self.make_job_hierarchy()
12300880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.mkdir('not-a-job')
12310880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        open('not-a-dir', 'w').close()
1232ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
123324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1234ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _run_get_directories(self, cls, expected_list):
1235ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `get_job_directories()` for the given class.
1236ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1237ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Calls the method, and asserts that the returned list of
1238ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        directories matches the expected return value.
1239ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1240ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param expected_list Expected return value from the call.
1241ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1242ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        dirlist = cls.get_job_directories()
1243ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(set(dirlist), set(expected_list))
1244ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
124524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1246ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_get_regular_jobs(self):
1247ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `RegularJobDirectory.get_job_directories()`."""
1248ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_get_directories(job_directories.RegularJobDirectory,
12490880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette                                  self.REGULAR_JOBLIST)
1250ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
125124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1252ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_get_special_jobs(self):
1253ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `SpecialJobDirectory.get_job_directories()`."""
1254ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_get_directories(job_directories.SpecialJobDirectory,
12550880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette                                  self.SPECIAL_JOBLIST)
1256ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1257ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1258ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass AddJobsTests(_TempResultsDirTestBase):
1259ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `Offloader._add_new_jobs()`."""
1260ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
12610880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    MOREJOBS = ['115-fubar', '116-fubar', '117-fubar', '118-snafu']
1262ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1263ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1264ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(AddJobsTests, self).setUp()
126522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._initial_job_names = (
126622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette            set(self.REGULAR_JOBLIST) | set(self.SPECIAL_JOBLIST))
12670880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self.make_job_hierarchy()
12680880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._offloader = gs_offloader.Offloader(_get_options(['-a']))
126922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.StubOutWithMock(logging, 'debug')
1270ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
127124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
127222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette    def _run_add_new_jobs(self, expected_key_set):
1273ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Basic test assertions for `_add_new_jobs()`.
1274ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1275ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Asserts the following:
1276ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The keys in the offloader's `_open_jobs` dictionary
1277ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            matches the expected set of keys.
1278ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * For every job in `_open_jobs`, the job has the expected
1279ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            directory name.
1280ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1281ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
128222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        count = len(expected_key_set) - len(self._offloader._open_jobs)
128322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        logging.debug(mox.IgnoreArg(), count)
128422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.ReplayAll()
128522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._offloader._add_new_jobs()
1286ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(expected_key_set,
1287ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                         set(self._offloader._open_jobs.keys()))
1288ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for jobkey, job in self._offloader._open_jobs.items():
1289ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self.assertEqual(jobkey, job._dirname)
129022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.VerifyAll()
129122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.ResetAll()
1292ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
129324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1294ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_add_jobs_empty(self):
1295ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test adding jobs to an empty dictionary.
1296ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1297ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Calls the offloader's `_add_new_jobs()`, then perform
1298ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the assertions of `self._check_open_jobs()`.
1299ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1300ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
130122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_add_new_jobs(self._initial_job_names)
1302ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
130324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1304ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_add_jobs_non_empty(self):
1305ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test adding jobs to a non-empty dictionary.
1306ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1307ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Calls the offloader's `_add_new_jobs()` twice; once from
1308ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        initial conditions, and then again after adding more
1309ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        directories.  After the second call, perform the assertions
1310ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        of `self._check_open_jobs()`.  Additionally, assert that
1311ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        keys added by the first call still map to their original
1312ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job object after the second call.
1313ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1314ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
131522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_add_new_jobs(self._initial_job_names)
1316ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        jobs_copy = self._offloader._open_jobs.copy()
13170880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.MOREJOBS:
13180880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(d)
131922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_add_new_jobs(self._initial_job_names |
132022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette                                 set(self.MOREJOBS))
1321ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for key in jobs_copy.keys():
1322ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self.assertIs(jobs_copy[key],
1323ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                          self._offloader._open_jobs[key])
1324ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1325ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1326ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass JobStateTests(_TempResultsDirTestBase):
1327ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for job state predicates.
1328ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1329ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    This tests for the expected results from the
1330ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `is_offloaded()` and `is_reportable()` predicate
1331ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    methods.
1332ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1333ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
1334ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1335ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_unfinished_job(self):
1336ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test that an unfinished job reports the correct state.
1337ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1338ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job is "unfinished" if it isn't marked complete in the
1339ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        database.  A job in this state is neither "complete" nor
1340ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        "reportable".
1341ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1342ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
13430880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        job = self.make_job(self.REGULAR_JOBLIST[0])
1344ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_offloaded())
1345ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_reportable())
1346ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
134724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1348ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_incomplete_job(self):
1349ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test that an incomplete job reports the correct state.
1350ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1351ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job is "incomplete" if exactly one attempt has been made
1352ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        to offload the job, but its results directory still exists.
1353ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job in this state is neither "complete" nor "reportable".
1354ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1355ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
13560880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        job = self.make_job(self.REGULAR_JOBLIST[0])
1357ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job.set_incomplete()
1358ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_offloaded())
1359ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_reportable())
1360ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
136124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1362ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_reportable_job(self):
1363ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test that a reportable job reports the correct state.
1364ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1365ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job is "reportable" if more than one attempt has been made
1366ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        to offload the job, and its results directory still exists.
1367ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job in this state is "reportable", but not "complete".
1368ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1369ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
13700880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        job = self.make_job(self.REGULAR_JOBLIST[0])
1371ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job.set_reportable()
1372ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_offloaded())
1373ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(job.is_reportable())
1374ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
137524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1376ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_completed_job(self):
1377ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test that a completed job reports the correct state.
1378ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1379ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job is "completed" if at least one attempt has been made
1380ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        to offload the job, and its results directory still exists.
1381ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        A job in this state is "complete", and not "reportable".
1382ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1383ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
13840880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        job = self.make_job(self.REGULAR_JOBLIST[0])
1385ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job.set_complete()
1386ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(job.is_offloaded())
1387ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(job.is_reportable())
1388ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1389ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1390ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass ReportingTests(_TempResultsDirTestBase):
1391ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `Offloader._update_offload_results()`."""
1392ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1393ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1394ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(ReportingTests, self).setUp()
1395ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader = gs_offloader.Offloader(_get_options([]))
1396ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.StubOutWithMock(email_manager.manager,
1397ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                                 'send_email')
139822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.StubOutWithMock(logging, 'debug')
1399ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
140024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1401ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _add_job(self, jobdir):
1402ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Add a job to the dictionary of unfinished jobs."""
1403ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        j = self.make_job(jobdir)
1404ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader._open_jobs[j._dirname] = j
1405ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        return j
1406ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
140724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
140822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette    def _expect_log_message(self, new_open_jobs, with_failures):
140922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """Mock expected logging calls.
141022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
141122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        `_update_offload_results()` logs one message with the number
141222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        of jobs removed from the open job set and the number of jobs
141322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        still remaining.  Additionally, if there are reportable
141422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        jobs, then it logs the number of jobs that haven't yet
141522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        offloaded.
141622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
141722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        This sets up the logging calls using `new_open_jobs` to
141822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        figure the job counts.  If `with_failures` is true, then
141922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        the log message is set up assuming that all jobs in
142022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        `new_open_jobs` have offload failures.
142122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
142222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        @param new_open_jobs New job set for calculating counts
142322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette                             in the messages.
142422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        @param with_failures Whether the log message with a
142522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette                             failure count is expected.
142622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
142722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """
142822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        count = len(self._offloader._open_jobs) - len(new_open_jobs)
142922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        logging.debug(mox.IgnoreArg(), count, len(new_open_jobs))
143022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        if with_failures:
143122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette            logging.debug(mox.IgnoreArg(), len(new_open_jobs))
143222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
143324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1434ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _run_update_no_report(self, new_open_jobs):
1435ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Call `_update_offload_results()` expecting no report.
1436ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1437ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are set up by the caller.  This calls
1438ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_update_offload_results()` once, and then checks these
1439ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        assertions:
1440ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The offloader's `_next_report_time` field is unchanged.
1441ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The offloader's new `_open_jobs` field contains only
1442ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            the entries in `new_open_jobs`.
1443ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The email_manager's `send_email` stub wasn't called.
1444ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1445ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param new_open_jobs A dictionary representing the expected
1446ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             new value of the offloader's
1447ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             `_open_jobs` field.
1448ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1449ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ReplayAll()
1450ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        next_report_time = self._offloader._next_report_time
1451ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader._update_offload_results()
1452ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(next_report_time,
1453ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                         self._offloader._next_report_time)
1454ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(self._offloader._open_jobs, new_open_jobs)
1455ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.VerifyAll()
1456ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ResetAll()
1457ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
145824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1459ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _run_update_with_report(self, new_open_jobs):
1460ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Call `_update_offload_results()` expecting an e-mail report.
1461ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1462ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are set up by the caller.  This calls
1463ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_update_offload_results()` once, and then checks these
1464ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        assertions:
1465ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The offloader's `_next_report_time` field is updated
1466ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            to an appropriate new time.
1467ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The offloader's new `_open_jobs` field contains only
1468ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            the entries in `new_open_jobs`.
1469ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The email_manager's `send_email` stub was called.
1470ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1471ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param new_open_jobs A dictionary representing the expected
1472ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             new value of the offloader's
1473ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             `_open_jobs` field.
1474ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
147522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        logging.debug(mox.IgnoreArg())
1476ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        email_manager.manager.send_email(
1477ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg())
1478ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ReplayAll()
1479ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        t0 = time.time() + gs_offloader.REPORT_INTERVAL_SECS
1480ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader._update_offload_results()
1481ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        t1 = time.time() + gs_offloader.REPORT_INTERVAL_SECS
1482ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        next_report_time = self._offloader._next_report_time
1483ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertGreaterEqual(next_report_time, t0)
1484ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertLessEqual(next_report_time, t1)
1485ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(self._offloader._open_jobs, new_open_jobs)
1486ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.VerifyAll()
1487ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ResetAll()
1488ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
148924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1490ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_no_jobs(self):
1491ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with no open jobs.
1492ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1493ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an empty `_open_jobs` list and
1494ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_next_report_time` in the past.  Expected result is no
1495ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        e-mail report, and an empty `_open_jobs` list.
1496ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1497ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
149822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message({}, False)
1499ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_update_no_report({})
1500ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
150124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1502ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_all_completed(self):
1503ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with only complete jobs.
1504ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1505ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1506ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only completed jobs and `_next_report_time` in the past.
1507ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Expected result is no e-mail report, and an empty
1508ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_open_jobs` list.
1509ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1510ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
15110880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1512ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d).set_complete()
151322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message({}, False)
1514ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_update_no_report({})
1515ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
151624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1517ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_none_finished(self):
1518ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with only unfinished jobs.
1519ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1520ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1521ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only unfinished jobs and `_next_report_time` in the past.
1522ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Expected result is no e-mail report, and no change to the
1523ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_open_jobs` list.
1524ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1525ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
15260880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1527ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d)
152822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
152922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, False)
153022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_no_report(new_jobs)
1531ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
153224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1533ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_none_reportable(self):
1534ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with only incomplete jobs.
1535ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1536ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1537ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only incomplete jobs and `_next_report_time` in the past.
1538ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Expected result is no e-mail report, and no change to the
1539ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `_open_jobs` list.
1540ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1541ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
15420880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1543ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d).set_incomplete()
154422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
154522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, False)
154622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_no_report(new_jobs)
1547ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
154824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1549ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_report_not_ready(self):
1550ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` e-mail throttling.
1551ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1552ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1553ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only reportable jobs but with `_next_report_time` in
1554ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the future.  Expected result is no e-mail report, and no
1555ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        change to the `_open_jobs` list.
1556ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1557ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1558ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # N.B.  This test may fail if its run time exceeds more than
1559ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # about _MARGIN_SECS seconds.
15600880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1561ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d).set_reportable()
1562ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader._next_report_time += _MARGIN_SECS
156322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
156422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, True)
156522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_no_report(new_jobs)
1566ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
156724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1568ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_reportable(self):
1569ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `_update_offload_results()` with reportable jobs.
1570ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1571ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
1572ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only reportable jobs and with `_next_report_time` in
1573ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the past.  Expected result is an e-mail report, and no
1574ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        change to the `_open_jobs` list.
1575ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1576ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
15770880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1578ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d).set_reportable()
157922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
158022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, True)
158122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_with_report(new_jobs)
158222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
158324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
158422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette    def test_reportable_mixed(self):
158522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """Test `_update_offload_results()` with a mixture of jobs.
158622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
158722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        Initial conditions are an `_open_jobs` list consisting of
158822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        one reportable jobs and the remainder of the jobs
158922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        incomplete.  The value of `_next_report_time` is in the
159022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        past.  Expected result is an e-mail report that includes
159122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        both the reportable and the incomplete jobs, and no change
159222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        to the `_open_jobs` list.
159322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
159422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """
159522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._add_job(self.REGULAR_JOBLIST[0]).set_reportable()
159622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        for d in self.REGULAR_JOBLIST[1:]:
159722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette            self._add_job(d).set_incomplete()
159822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
159922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, True)
160022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_update_with_report(new_jobs)
1601ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1602ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1603ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteif __name__ == '__main__':
1604ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    unittest.main()
1605