14ad0c3b47ea2fcf52a0cb3fe7f3dc6b5f853836aAllen Li#!/usr/bin/python
297d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang# Copyright 2016 The Chromium OS Authors. All rights reserved.
3ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# Use of this source code is governed by a BSD-style license that can be
4ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# found in the LICENSE file.
5ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
65ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddowimport __builtin__
7ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport Queue
8ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport datetime
9ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport logging
10ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport os
11ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport shutil
122e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnetteimport signal
13ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodbyimport stat
14ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport sys
15ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport tempfile
16ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport time
17ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport unittest
18ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
199579b38072f8008b92623d7c30e3fc55c05c7561Allen Liimport mock
20ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport mox
21ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
22ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteimport common
235ed7e63aeec90dc0c6b4229a66bf161410aa86a6Allen Lifrom 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
26e8bc959e03680ed268d02f6979bf154691722d44Michael Tang#For unittest without cloud_client.proto compiled.
27e8bc959e03680ed268d02f6979bf154691722d44Michael Tangtry:
28e8bc959e03680ed268d02f6979bf154691722d44Michael Tang    from autotest_lib.site_utils import cloud_console_client
29e8bc959e03680ed268d02f6979bf154691722d44Michael Tangexcept ImportError:
30e8bc959e03680ed268d02f6979bf154691722d44Michael Tang    cloud_console_client = None
31beb9e01b8aebdd33b7c866fbdfef64bc77f139e5Prathmesh Prabhufrom autotest_lib.site_utils import gs_offloader
32beb9e01b8aebdd33b7c866fbdfef64bc77f139e5Prathmesh Prabhufrom autotest_lib.site_utils import job_directories
332d981eee42e4f9fb4f6d726b97aa8122322543beNingning Xiafrom autotest_lib.tko import models
34b41527d6f865688299dc5250f8d58baca9432777Allen Lifrom autotest_lib.utils import gslib
350f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tangfrom autotest_lib.site_utils import pubsub_utils
36b41527d6f865688299dc5250f8d58baca9432777Allen Lifrom chromite.lib import timeout_util
3724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
38ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# Test value to use for `days_old`, if nothing else is required.
39ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette_TEST_EXPIRATION_AGE = 7
40ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
41ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# When constructing sample time values for testing expiration,
42ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# allow this many seconds between the expiration time and the
43ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette# current time.
44ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette_MARGIN_SECS = 10.0
45ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
46ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
47ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnettedef _get_options(argv):
48ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Helper function to exercise command line parsing.
49ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
50ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    @param argv Value of sys.argv to be parsed.
51ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
52ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
53ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    sys.argv = ['bogus.py'] + argv
54ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    return gs_offloader.parse_options()
55ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
56ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
57ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodbydef is_fifo(path):
589358538d79b35ef0f586b7e9f2f0d6741f9c44c1Allen Li  """Determines whether a path is a fifo.
599358538d79b35ef0f586b7e9f2f0d6741f9c44c1Allen Li
609358538d79b35ef0f586b7e9f2f0d6741f9c44c1Allen Li  @param path: fifo path string.
619358538d79b35ef0f586b7e9f2f0d6741f9c44c1Allen Li  """
62ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby  return stat.S_ISFIFO(os.lstat(path).st_mode)
63ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby
64ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby
65dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basiclass OffloaderOptionsTests(mox.MoxTestBase):
66ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    """Tests for the `Offloader` constructor.
67ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette
68ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    Tests that offloader instance fields are set as expected
69ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    for given command line options.
70ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette
71ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    """
72ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette
73ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    _REGULAR_ONLY = set([job_directories.RegularJobDirectory])
74ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    _SPECIAL_ONLY = set([job_directories.SpecialJobDirectory])
75ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette    _BOTH = _REGULAR_ONLY | _SPECIAL_ONLY
76ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
7724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
78dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi    def setUp(self):
79dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        super(OffloaderOptionsTests, self).setUp()
80dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.mox.StubOutWithMock(utils, 'get_offload_gsuri')
81f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        gs_offloader.GS_OFFLOADING_ENABLED = True
820df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        gs_offloader.GS_OFFLOADER_MULTIPROCESSING = False
83dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi
8424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
85b41527d6f865688299dc5250f8d58baca9432777Allen Li    def _mock_get_sub_offloader(self, is_moblab, multiprocessing=False,
860f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang                               console_client=None, delete_age=0):
87dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        """Mock the process of getting the offload_dir function."""
88dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        if is_moblab:
89dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi            expected_gsuri = '%sresults/%s/%s/' % (
90dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                    global_config.global_config.get_config_value(
91dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                            'CROS', 'image_storage_server'),
92dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                    'Fa:ke:ma:c0:12:34', 'rand0m-uu1d')
93dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        else:
94dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi            expected_gsuri = utils.DEFAULT_OFFLOAD_GSURI
95dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        utils.get_offload_gsuri().AndReturn(expected_gsuri)
96b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = gs_offloader.GSOffloader(expected_gsuri,
970f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang            multiprocessing, delete_age, console_client)
98b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.mox.StubOutWithMock(gs_offloader, 'GSOffloader')
99e8bc959e03680ed268d02f6979bf154691722d44Michael Tang        if cloud_console_client:
100e8bc959e03680ed268d02f6979bf154691722d44Michael Tang            self.mox.StubOutWithMock(cloud_console_client,
101e8bc959e03680ed268d02f6979bf154691722d44Michael Tang                    'is_cloud_notification_enabled')
1020f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang        if console_client:
1030f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang            cloud_console_client.is_cloud_notification_enabled().AndReturn(True)
1040f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang            gs_offloader.GSOffloader(
1050f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang                    expected_gsuri, multiprocessing, delete_age,
1060f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang                    mox.IsA(cloud_console_client.PubSubBasedClient)).AndReturn(
1070f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang                        sub_offloader)
1080f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang        else:
109e8bc959e03680ed268d02f6979bf154691722d44Michael Tang            if cloud_console_client:
110e8bc959e03680ed268d02f6979bf154691722d44Michael Tang                cloud_console_client.is_cloud_notification_enabled().AndReturn(
111e8bc959e03680ed268d02f6979bf154691722d44Michael Tang                        False)
1120f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang            gs_offloader.GSOffloader(
1130f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang                expected_gsuri, multiprocessing, delete_age, None).AndReturn(
1140f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang                    sub_offloader)
115dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.mox.ReplayAll()
116b41527d6f865688299dc5250f8d58baca9432777Allen Li        return sub_offloader
117dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi
11824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
119ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_process_no_options(self):
120ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test default offloader options."""
121b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = self._mock_get_sub_offloader(False)
122ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(_get_options([]))
123ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
124ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
125ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
126b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
127b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
1285ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1295ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
130ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
13124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
132ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_process_all_option(self):
133ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --all option."""
134b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = self._mock_get_sub_offloader(False)
135ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(_get_options(['--all']))
136ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes), self._BOTH)
137ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
138b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
139b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
1405ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1415ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
142ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
14324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
144ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_process_hosts_option(self):
145ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --hosts option."""
146b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = self._mock_get_sub_offloader(False)
147ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
148ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--hosts']))
149ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
150ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._SPECIAL_ONLY)
151ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
152b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
153b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
1545ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1555ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
156ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
15724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
158ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_parallelism_option(self):
159ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --parallelism option."""
160b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = self._mock_get_sub_offloader(False)
161ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
162ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--parallelism', '2']))
163ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
164ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
165ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 2)
166b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
167b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
1685ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1695ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
170ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
17124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
172ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_delete_only_option(self):
173ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --delete_only option."""
174ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
175ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--delete_only']))
176ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
177ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
178ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
179b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertIsInstance(offloader._gs_offloader,
180b41527d6f865688299dc5250f8d58baca9432777Allen Li                              gs_offloader.FakeGSOffloader)
1815ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
1825ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
183ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
18424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
185df4751eaab3405bc4f564d033681d093958f0c10Simran Basi    def test_days_old_option(self):
186ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        """Test offloader handling for the --days_old option."""
187b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = self._mock_get_sub_offloader(False, delete_age=7)
188ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        offloader = gs_offloader.Offloader(
189ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                _get_options(['--days_old', '7']))
190ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(set(offloader._jobdir_classes),
191ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette                         self._REGULAR_ONLY)
192ef4b47dedcb759b46fd1e415172a688f1448df54J. Richard Barnette        self.assertEqual(offloader._processes, 1)
193b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
194b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
1955ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 7)
1965ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 7)
197ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
19824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
199dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi    def test_moblab_gsuri_generation(self):
200dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        """Test offloader construction for Moblab."""
201b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = self._mock_get_sub_offloader(True)
202dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        offloader = gs_offloader.Offloader(_get_options([]))
203dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.assertEqual(set(offloader._jobdir_classes),
204dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                         self._REGULAR_ONLY)
205dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self.assertEqual(offloader._processes, 1)
206b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
207b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
2085ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._upload_age_limit, 0)
2095ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.assertEqual(offloader._delete_age_limit, 0)
210dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi
211ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
212f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi    def test_globalconfig_offloading_flag(self):
213f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        """Test enabling of --delete_only via global_config."""
214f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        gs_offloader.GS_OFFLOADING_ENABLED = False
215f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi        offloader = gs_offloader.Offloader(
216f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi                _get_options([]))
217b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertIsInstance(offloader._gs_offloader,
218b41527d6f865688299dc5250f8d58baca9432777Allen Li                             gs_offloader.FakeGSOffloader)
219f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi
2200df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang    def test_offloader_multiprocessing_flag_set(self):
2210df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        """Test multiprocessing is set."""
222b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = self._mock_get_sub_offloader(True, True)
2230df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offloader = gs_offloader.Offloader(_get_options(['-m']))
224b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
225b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
2260df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.mox.VerifyAll()
2270df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang
2280df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang    def test_offloader_multiprocessing_flag_not_set_default_false(self):
2290df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        """Test multiprocessing is set."""
2300df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        gs_offloader.GS_OFFLOADER_MULTIPROCESSING = False
231b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = self._mock_get_sub_offloader(True, False)
2320df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offloader = gs_offloader.Offloader(_get_options([]))
233b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
234b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
2350df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.mox.VerifyAll()
2360df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang
2370df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang    def test_offloader_multiprocessing_flag_not_set_default_true(self):
2380df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        """Test multiprocessing is set."""
2390df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        gs_offloader.GS_OFFLOADER_MULTIPROCESSING = True
240b41527d6f865688299dc5250f8d58baca9432777Allen Li        sub_offloader = self._mock_get_sub_offloader(True, True)
2410df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        offloader = gs_offloader.Offloader(_get_options([]))
242b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
243b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
2440df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang        self.mox.VerifyAll()
2450df2eb4e1e8638a1a165e8f2dc3b9230f85acf06Michael Tang
24697d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
2470f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang    def test_offloader_pubsub_enabled(self):
24897d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        """Test multiprocessing is set."""
249e8bc959e03680ed268d02f6979bf154691722d44Michael Tang        if not cloud_console_client:
250e8bc959e03680ed268d02f6979bf154691722d44Michael Tang            return
2510f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang        self.mox.StubOutWithMock(pubsub_utils, "PubSubClient")
2520f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang        sub_offloader = self._mock_get_sub_offloader(True, False,
2530f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang                cloud_console_client.PubSubBasedClient())
2540f553bd773170c8ddb80d6061cdc0f133ba239b6Michael Tang        offloader = gs_offloader.Offloader(_get_options([]))
255b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(offloader._gs_offloader,
256b41527d6f865688299dc5250f8d58baca9432777Allen Li                         sub_offloader)
25797d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang        self.mox.VerifyAll()
25897d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
259f3e305f2c1342d8dd271256c2594ae54072c514bSimran Basi
260ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnettedef _make_timestamp(age_limit, is_expired):
2615ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    """Create a timestamp for use by `job_directories.is_job_expired()`.
262ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
263ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    The timestamp will meet the syntactic requirements for
2645ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    timestamps used as input to `is_job_expired()`.  If
265ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `is_expired` is true, the timestamp will be older than
266ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `age_limit` days before the current time; otherwise, the
267ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    date will be younger.
268ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
269ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    @param age_limit    The number of days before expiration of the
270ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        target timestamp.
271ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    @param is_expired   Whether the timestamp should be expired
272ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        relative to `age_limit`.
273ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
274ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
275ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    seconds = -_MARGIN_SECS
276ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    if is_expired:
277ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        seconds = -seconds
278ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    delta = datetime.timedelta(days=age_limit, seconds=seconds)
279ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    reference_time = datetime.datetime.now() - delta
280dfea368e5c830b1d7950ced5ee7b191e3b141ca3Dan Shi    return reference_time.strftime(time_utils.TIME_FMT)
281ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
282ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
283ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass JobExpirationTests(unittest.TestCase):
2845ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    """Tests to exercise `job_directories.is_job_expired()`."""
285ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
286ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_expired(self):
287ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test detection of an expired job."""
288ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        timestamp = _make_timestamp(_TEST_EXPIRATION_AGE, True)
289ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(
2905ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow            job_directories.is_job_expired(
291ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                _TEST_EXPIRATION_AGE, timestamp))
292ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
293ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
294ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_alive(self):
295ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test detection of a job that's not expired."""
296ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # N.B.  This test may fail if its run time exceeds more than
297ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        # about _MARGIN_SECS seconds.
298ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        timestamp = _make_timestamp(_TEST_EXPIRATION_AGE, False)
299ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(
3005ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow            job_directories.is_job_expired(
301ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                _TEST_EXPIRATION_AGE, timestamp))
302ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
303ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
304ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass _MockJobDirectory(job_directories._JobDirectory):
305ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Subclass of `_JobDirectory` used as a helper for tests."""
306ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
307ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    GLOB_PATTERN = '[0-9]*-*'
308ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
30924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
310ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def __init__(self, resultsdir):
311ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Create new job in initial state."""
312ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(_MockJobDirectory, self).__init__(resultsdir)
313ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._timestamp = None
3145ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.queue_args = [resultsdir, os.path.dirname(resultsdir), self._timestamp]
315ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
31624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
317ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def get_timestamp_if_finished(self):
318ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        return self._timestamp
319ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
32024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
321ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_finished(self, days_old):
322ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job appear to be finished.
323ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
324ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        After calling this function, calls to `enqueue_offload()`
325ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        will find this job as finished, but not expired and ready
326ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for offload.  Note that when `days_old` is 0,
327ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `enqueue_offload()` will treat a finished job as eligible
328ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for offload.
329ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
330ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param days_old The value of the `days_old` parameter that
331ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        will be passed to `enqueue_offload()` for
332ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        testing.
333ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
334ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
335ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._timestamp = _make_timestamp(days_old, False)
3365ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.queue_args[2] = self._timestamp
337ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
33824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
339ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_expired(self, days_old):
340ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job eligible to be offloaded.
341ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
342ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        After calling this function, calls to `offload` will attempt
343ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        to offload this job.
344ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
345ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param days_old The value of the `days_old` parameter that
346ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        will be passed to `enqueue_offload()` for
347ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                        testing.
348ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
349ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
350ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._timestamp = _make_timestamp(days_old, True)
3515ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.queue_args[2] = self._timestamp
352ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
35324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
354ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_incomplete(self):
355ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job appear to have failed offload just once."""
356b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.offload_count += 1
357b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.first_offload_start = time.time()
358b41527d6f865688299dc5250f8d58baca9432777Allen Li        if not os.path.isdir(self.dirname):
359b41527d6f865688299dc5250f8d58baca9432777Allen Li            os.mkdir(self.dirname)
360ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
36124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
362ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_reportable(self):
363ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job be reportable."""
364ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.set_incomplete()
365b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.offload_count += 1
366ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
36724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
368ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def set_complete(self):
369ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make this job be completed."""
370b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.offload_count += 1
371b41527d6f865688299dc5250f8d58baca9432777Allen Li        if os.path.isdir(self.dirname):
372b41527d6f865688299dc5250f8d58baca9432777Allen Li            os.rmdir(self.dirname)
373ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
374ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
3751e10e92049f4b2724ea43186083e995e418f9802Simran Basi    def process_gs_instructions(self):
3761e10e92049f4b2724ea43186083e995e418f9802Simran Basi        """Always still offload the job directory."""
3771e10e92049f4b2724ea43186083e995e418f9802Simran Basi        return True
3781e10e92049f4b2724ea43186083e995e418f9802Simran Basi
3791e10e92049f4b2724ea43186083e995e418f9802Simran Basi
3809f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnetteclass CommandListTests(unittest.TestCase):
381b41527d6f865688299dc5250f8d58baca9432777Allen Li    """Tests for `_get_cmd_list()`."""
3829f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
383e93c85778aa8b22aa88482c43092133d59434147MK Ryu    def _command_list_assertions(self, job, use_rsync=True, multi=False):
384b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Call `_get_cmd_list()` and check the return value.
3859f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3869f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        Check the following assertions:
3879f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette          * The command name (argv[0]) is 'gsutil'.
388e93c85778aa8b22aa88482c43092133d59434147MK Ryu          * '-m' option (argv[1]) is on when the argument, multi, is True.
3899f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette          * The arguments contain the 'cp' subcommand.
3909f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette          * The next-to-last argument (the source directory) is the
3919f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette            job's `queue_args[0]`.
392dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi          * The last argument (the destination URL) is the job's
393dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi            'queue_args[1]'.
3949f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
3959f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        @param job A job with properly calculated arguments to
396b41527d6f865688299dc5250f8d58baca9432777Allen Li                   `_get_cmd_list()`
397e93c85778aa8b22aa88482c43092133d59434147MK Ryu        @param use_rsync True when using 'rsync'. False when using 'cp'.
398e93c85778aa8b22aa88482c43092133d59434147MK Ryu        @param multi True when using '-m' option for gsutil.
3999f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
4009f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        """
40124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        test_bucket_uri = 'gs://a-test-bucket'
40224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
40324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        gs_offloader.USE_RSYNC_ENABLED = use_rsync
40424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
405b41527d6f865688299dc5250f8d58baca9432777Allen Li        command = gs_offloader._get_cmd_list(
406e93c85778aa8b22aa88482c43092133d59434147MK Ryu                multi, job.queue_args[0],
407e93c85778aa8b22aa88482c43092133d59434147MK Ryu                os.path.join(test_bucket_uri, job.queue_args[1]))
40824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
409365049f691c80802030f62cf2fce345bb670e00dDan Shi        self.assertEqual(command[0], 'gsutil')
410e93c85778aa8b22aa88482c43092133d59434147MK Ryu        if multi:
411e93c85778aa8b22aa88482c43092133d59434147MK Ryu            self.assertEqual(command[1], '-m')
4129f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self.assertEqual(command[-2], job.queue_args[0])
41324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
41424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        if use_rsync:
41524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertTrue('rsync' in command)
41624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertEqual(command[-1],
41724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich                             os.path.join(test_bucket_uri, job.queue_args[0]))
41824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        else:
41924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertTrue('cp' in command)
42024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich            self.assertEqual(command[-1],
42124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich                             os.path.join(test_bucket_uri, job.queue_args[1]))
42224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
4239f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
424b41527d6f865688299dc5250f8d58baca9432777Allen Li    def test__get_cmd_list_regular(self):
425b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test `_get_cmd_list()` as for a regular job."""
4269f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        job = _MockJobDirectory('118-debug')
4279f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self._command_list_assertions(job)
4289f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
42924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
430b41527d6f865688299dc5250f8d58baca9432777Allen Li    def test__get_cmd_list_special(self):
431b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test `_get_cmd_list()` as for a special job."""
4329f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        job = _MockJobDirectory('hosts/host1/118-reset')
4339f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette        self._command_list_assertions(job)
4349f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
4359f4be0d66119211b3ece24bb985f1412d1f61322J. Richard Barnette
43624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich    def test_get_cmd_list_regular_no_rsync(self):
437b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test `_get_cmd_list()` as for a regular job."""
43824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        job = _MockJobDirectory('118-debug')
43924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        self._command_list_assertions(job, use_rsync=False)
44024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
44124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
44224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich    def test_get_cmd_list_special_no_rsync(self):
443b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test `_get_cmd_list()` as for a special job."""
44424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        job = _MockJobDirectory('hosts/host1/118-reset')
44524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich        self._command_list_assertions(job, use_rsync=False)
44624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
44724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
448e93c85778aa8b22aa88482c43092133d59434147MK Ryu    def test_get_cmd_list_regular_multi(self):
449b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test `_get_cmd_list()` as for a regular job with True multi."""
450e93c85778aa8b22aa88482c43092133d59434147MK Ryu        job = _MockJobDirectory('118-debug')
451e93c85778aa8b22aa88482c43092133d59434147MK Ryu        self._command_list_assertions(job, multi=True)
452e93c85778aa8b22aa88482c43092133d59434147MK Ryu
453e93c85778aa8b22aa88482c43092133d59434147MK Ryu
454b41527d6f865688299dc5250f8d58baca9432777Allen Li    def test__get_cmd_list_special_multi(self):
455b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test `_get_cmd_list()` as for a special job with True multi."""
456e93c85778aa8b22aa88482c43092133d59434147MK Ryu        job = _MockJobDirectory('hosts/host1/118-reset')
457e93c85778aa8b22aa88482c43092133d59434147MK Ryu        self._command_list_assertions(job, multi=True)
458e93c85778aa8b22aa88482c43092133d59434147MK Ryu
459e93c85778aa8b22aa88482c43092133d59434147MK Ryu
460dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnetteclass _MockJob(object):
461dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    """Class to mock the return value of `AFE.get_jobs()`."""
462dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def __init__(self, created):
463dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.created_on = created
464dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
465dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
466dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnetteclass _MockHostQueueEntry(object):
467dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    """Class to mock the return value of `AFE.get_host_queue_entries()`."""
468dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def __init__(self, finished):
469dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.finished_on = finished
470dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
471dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
472dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnetteclass _MockSpecialTask(object):
473dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    """Class to mock the return value of `AFE.get_special_tasks()`."""
474dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def __init__(self, finished):
475dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.time_finished = finished
476dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
477dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
4782c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnetteclass JobDirectorySubclassTests(mox.MoxTestBase):
4792c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette    """Test specific to RegularJobDirectory and SpecialJobDirectory.
4803e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
4813e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    This provides coverage for the implementation in both
4823e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    RegularJobDirectory and SpecialJobDirectory.
4833e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
4843e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    """
4853e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
4863e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def setUp(self):
4872c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        super(JobDirectorySubclassTests, self).setUp()
488dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.StubOutWithMock(job_directories._AFE, 'get_jobs')
489dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.StubOutWithMock(job_directories._AFE,
490dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 'get_host_queue_entries')
491dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.StubOutWithMock(job_directories._AFE,
492dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 'get_special_tasks')
4933e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
49424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
4952c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette    def test_regular_job_fields(self):
4962c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """Test the constructor for `RegularJobDirectory`.
4972c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
498b41527d6f865688299dc5250f8d58baca9432777Allen Li        Construct a regular job, and assert that the `dirname`
4992c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        and `_id` attributes are set as expected.
5002c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5012c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """
5022c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        resultsdir = '118-fubar'
5032c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.RegularJobDirectory(resultsdir)
504b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(job.dirname, resultsdir)
505cf4d2032ea4bf5af680383f36308d581876bbbb0Dan Shi        self.assertEqual(job._id, 118)
5062c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
50724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
5082c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette    def test_special_job_fields(self):
5092c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """Test the constructor for `SpecialJobDirectory`.
5102c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
511b41527d6f865688299dc5250f8d58baca9432777Allen Li        Construct a special job, and assert that the `dirname`
5122c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        and `_id` attributes are set as expected.
5132c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
5142c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        """
5152c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        destdir = 'hosts/host1'
5162c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        resultsdir = destdir + '/118-reset'
5172c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.SpecialJobDirectory(resultsdir)
518b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(job.dirname, resultsdir)
519cf4d2032ea4bf5af680383f36308d581876bbbb0Dan Shi        self.assertEqual(job._id, 118)
5202c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette
52124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
522dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette    def _check_finished_job(self, jobtime, hqetimes, expected):
523dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        """Mock and test behavior of a finished job.
524dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
525dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        Initialize the mocks for a call to
526dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        `get_timestamp_if_finished()`, then simulate one call.
527dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        Assert that the returned timestamp matches the passed
528dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        in expected value.
529dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
530dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        @param jobtime Time used to construct a _MockJob object.
531dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        @param hqetimes List of times used to construct
532dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        _MockHostQueueEntry objects.
533dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        @param expected Expected time to be returned by
534dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        get_timestamp_if_finished
535dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
536dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        """
537dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job = job_directories.RegularJobDirectory('118-fubar')
538dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_jobs(
539dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, finished=True).AndReturn(
540dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        [_MockJob(jobtime)])
541dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_host_queue_entries(
542dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                finished_on__isnull=False,
543dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                job_id=job._id).AndReturn(
544dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                        [_MockHostQueueEntry(t) for t in hqetimes])
545dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.ReplayAll()
546dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.assertEqual(expected, job.get_timestamp_if_finished())
547dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
548dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
549dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
5503e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_finished_regular_job(self):
5513e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for a finished regular job.
5523e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
5533e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
5543e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `RegularJobDirectory.get_timestamp_if_finished()` when
5553e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is finished.
5563e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
5573e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
558dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        created_timestamp = _make_timestamp(1, True)
559dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        hqe_timestamp = _make_timestamp(0, True)
560dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(created_timestamp,
561dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 [hqe_timestamp],
562dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 hqe_timestamp)
563fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
56424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
565fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi    def test_finished_regular_job_multiple_hqes(self):
566fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """Test getting the timestamp for a regular job with multiple hqes.
567fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
568fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        Tests the return value for
569fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        `RegularJobDirectory.get_timestamp_if_finished()` when
570fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        the AFE indicates the job is finished and the job has multiple host
571fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        queue entries.
572fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
573dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        Tests that the returned timestamp is the latest timestamp in
574dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        the list of HQEs, regardless of the returned order.
575dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette
576fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """
577fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        created_timestamp = _make_timestamp(2, True)
578fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        older_hqe_timestamp = _make_timestamp(1, True)
579fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        newer_hqe_timestamp = _make_timestamp(0, True)
580dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        hqe_list = [older_hqe_timestamp,
581dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                    newer_hqe_timestamp]
582dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(created_timestamp,
583dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 hqe_list,
584dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 newer_hqe_timestamp)
585dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.ResetAll()
586dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        hqe_list.reverse()
587dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(created_timestamp,
588dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 hqe_list,
589dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                                 newer_hqe_timestamp)
590fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
59124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
592fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi    def test_finished_regular_job_null_finished_times(self):
593fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """Test getting the timestamp for an aborted regular job.
594fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
595fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        Tests the return value for
596fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        `RegularJobDirectory.get_timestamp_if_finished()` when
597fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        the AFE indicates the job is finished and the job has aborted host
598fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        queue entries.
599fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi
600fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        """
601fb98e46b33c3f683173b980e027523dfb91f2759Simran Basi        timestamp = _make_timestamp(0, True)
602dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self._check_finished_job(timestamp, [], timestamp)
6033e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
60424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6053e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_unfinished_regular_job(self):
6063e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for an unfinished regular job.
6073e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6083e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
6093e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `RegularJobDirectory.get_timestamp_if_finished()` when
6103e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is not finished.
6113e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6123e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
6133e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        job = job_directories.RegularJobDirectory('118-fubar')
614dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_jobs(
615dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, finished=True).AndReturn([])
6163e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.mox.ReplayAll()
6173e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.assertIsNone(job.get_timestamp_if_finished())
618dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
6193e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
62024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6213e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_finished_special_job(self):
6223e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for a finished special job.
6233e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6243e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
6253e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `SpecialJobDirectory.get_timestamp_if_finished()` when
6263e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is finished.
6273e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6283e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
6292c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.SpecialJobDirectory(
6302c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette                'hosts/host1/118-reset')
6313e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        timestamp = _make_timestamp(0, True)
632dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_special_tasks(
633dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, is_complete=True).AndReturn(
634dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                    [_MockSpecialTask(timestamp)])
6353e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.mox.ReplayAll()
6363e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.assertEqual(timestamp,
6373e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette                         job.get_timestamp_if_finished())
638dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
6393e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
64024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6413e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette    def test_unfinished_special_job(self):
6423e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """Test getting the timestamp for an unfinished special job.
6433e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6443e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        Tests the return value for
6453e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        `SpecialJobDirectory.get_timestamp_if_finished()` when
6463e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        the AFE indicates the job is not finished.
6473e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6483e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        """
6492c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        job = job_directories.SpecialJobDirectory(
6502c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette                'hosts/host1/118-reset')
651dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        job_directories._AFE.get_special_tasks(
652dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette                id=job._id, is_complete=True).AndReturn([])
6533e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.mox.ReplayAll()
6543e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette        self.assertIsNone(job.get_timestamp_if_finished())
655dd0227d5503b9c0ea63837eec26f87c4e4958e4aJ. Richard Barnette        self.mox.VerifyAll()
6563e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
6573e3ed6a9627a156a2240d607565e7c6f78151f28J. Richard Barnette
658b41527d6f865688299dc5250f8d58baca9432777Allen Liclass _TempResultsDirTestCase(unittest.TestCase):
659b41527d6f865688299dc5250f8d58baca9432777Allen Li    """Mixin class for tests using a temporary results directory."""
660ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
6610880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    REGULAR_JOBLIST = [
6620880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        '111-fubar', '112-fubar', '113-fubar', '114-snafu']
6630880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    HOST_LIST = ['host1', 'host2', 'host3']
6640880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    SPECIAL_JOBLIST = [
6650880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        'hosts/host1/333-reset', 'hosts/host1/334-reset',
6660880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        'hosts/host2/444-reset', 'hosts/host3/555-reset']
6670880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
66824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
669ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
670b41527d6f865688299dc5250f8d58baca9432777Allen Li        super(_TempResultsDirTestCase, self).setUp()
6710880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._resultsroot = tempfile.mkdtemp()
6720880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._cwd = os.getcwd()
6730880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.chdir(self._resultsroot)
674ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
67524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
676ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def tearDown(self):
6770880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.chdir(self._cwd)
678ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        shutil.rmtree(self._resultsroot)
679b41527d6f865688299dc5250f8d58baca9432777Allen Li        super(_TempResultsDirTestCase, self).tearDown()
680ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
68124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
682ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def make_job(self, jobdir):
683ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Create a job with results in `self._resultsroot`.
684ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
685ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param jobdir Name of the subdirectory to be created in
686ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                      `self._resultsroot`.
687ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
688ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
6890880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.mkdir(jobdir)
6900880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        return _MockJobDirectory(jobdir)
6910880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
69224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
6930880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    def make_job_hierarchy(self):
6940880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        """Create a sample hierarchy of job directories.
6950880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
6960880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        `self.REGULAR_JOBLIST` is a list of directories for regular
6970880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        jobs to be created; `self.SPECIAL_JOBLIST` is a list of
6980880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        directories for special jobs to be created.
6990880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette
7000880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        """
7010880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
7020880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(d)
7030880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        hostsdir = 'hosts'
7040880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.mkdir(hostsdir)
7050880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for host in self.HOST_LIST:
7060880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(os.path.join(hostsdir, host))
7070880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.SPECIAL_JOBLIST:
7080880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(d)
709ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
710ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
711b41527d6f865688299dc5250f8d58baca9432777Allen Liclass _TempResultsDirTestBase(_TempResultsDirTestCase, mox.MoxTestBase):
712b41527d6f865688299dc5250f8d58baca9432777Allen Li    """Base Mox test class for tests using a temporary results directory."""
713b41527d6f865688299dc5250f8d58baca9432777Allen Li
714b41527d6f865688299dc5250f8d58baca9432777Allen Li
71580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhuclass FailedOffloadsLogTest(_TempResultsDirTestBase):
71680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    """Test the formatting of failed offloads log file."""
71780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # Below is partial sample of a failed offload log file.  This text is
71880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # deliberately hard-coded and then parsed to create the test data; the idea
71980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # is to make sure the actual text format will be reviewed by a human being.
72080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    #
72180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # first offload      count  directory
72280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    # --+----1----+----  ----+ ----+----1----+----2----+----3
72380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    _SAMPLE_DIRECTORIES_REPORT = '''\
72480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    =================== ======  ==============================
72580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:09:26      1  118-fubar
72680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:19:23      2  117-fubar
72780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:29:20      6  116-fubar
72880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:39:17     24  115-fubar
72980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:49:14    120  114-fubar
73080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 15:59:11    720  113-fubar
73180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 16:09:08   5040  112-fubar
73280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    2014-03-14 16:19:05  40320  111-fubar
73380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    '''
73480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
73580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    def setUp(self):
73680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        super(FailedOffloadsLogTest, self).setUp()
73780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self._offloader = gs_offloader.Offloader(_get_options([]))
73880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self._joblist = []
73980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        for line in self._SAMPLE_DIRECTORIES_REPORT.split('\n')[1 : -1]:
74080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            date_, time_, count, dir_ = line.split()
74180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            job = _MockJobDirectory(dir_)
742b41527d6f865688299dc5250f8d58baca9432777Allen Li            job.offload_count = int(count)
74380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            timestruct = time.strptime("%s %s" % (date_, time_),
74480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                                       gs_offloader.FAILED_OFFLOADS_TIME_FORMAT)
745b41527d6f865688299dc5250f8d58baca9432777Allen Li            job.first_offload_start = time.mktime(timestruct)
74680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            # enter the jobs in reverse order, to make sure we
74780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            # test that the output will be sorted.
74880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            self._joblist.insert(0, job)
74980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
75080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
75180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    def assert_report_well_formatted(self, report_file):
7529358538d79b35ef0f586b7e9f2f0d6741f9c44c1Allen Li        """Assert that report file is well formatted.
7539358538d79b35ef0f586b7e9f2f0d6741f9c44c1Allen Li
7549358538d79b35ef0f586b7e9f2f0d6741f9c44c1Allen Li        @param report_file: Path to report file
7559358538d79b35ef0f586b7e9f2f0d6741f9c44c1Allen Li        """
75680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        with open(report_file, 'r') as f:
75780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            report_lines = f.read().split()
75880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
75980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        for end_of_header_index in range(len(report_lines)):
76080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            if report_lines[end_of_header_index].startswith('=='):
76180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                break
76280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self.assertLess(end_of_header_index, len(report_lines),
76380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                        'Failed to find end-of-header marker in the report')
76480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
76580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        relevant_lines = report_lines[end_of_header_index:]
76680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        expected_lines = self._SAMPLE_DIRECTORIES_REPORT.split()
76780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self.assertListEqual(relevant_lines, expected_lines)
76880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
76980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
77080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    def test_failed_offload_log_format(self):
77180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        """Trigger an e-mail report and check its contents."""
77280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        log_file = os.path.join(self._resultsroot, 'failed_log')
77380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        report = self._offloader._log_failed_jobs_locally(self._joblist,
77480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                                                          log_file=log_file)
77580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self.assert_report_well_formatted(log_file)
77680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
77780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
77880dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu    def test_failed_offload_file_overwrite(self):
77980dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        """Verify that we can saefly overwrite the log file."""
78080dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        log_file = os.path.join(self._resultsroot, 'failed_log')
78180dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        with open(log_file, 'w') as f:
78280dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu            f.write('boohoohoo')
78380dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        report = self._offloader._log_failed_jobs_locally(self._joblist,
78480dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu                                                          log_file=log_file)
78580dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu        self.assert_report_well_formatted(log_file)
78680dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
78780dfb1e9366b74f6c5a928e33793012e5a8ebc5aPrathmesh Prabhu
7882e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnetteclass OffloadDirectoryTests(_TempResultsDirTestBase):
7892e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    """Tests for `offload_dir()`."""
7902e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
7912e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def setUp(self):
7922e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        super(OffloadDirectoryTests, self).setUp()
7932e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        # offload_dir() logs messages; silence them.
7942e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._saved_loglevel = logging.getLogger().getEffectiveLevel()
7952e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        logging.getLogger().setLevel(logging.CRITICAL+1)
7962e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self._job = self.make_job(self.REGULAR_JOBLIST[0])
797b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.mox.StubOutWithMock(gs_offloader, '_get_cmd_list')
798b41527d6f865688299dc5250f8d58baca9432777Allen Li        alarm = mock.patch('signal.alarm', return_value=0)
799b41527d6f865688299dc5250f8d58baca9432777Allen Li        alarm.start()
800b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.addCleanup(alarm.stop)
8012d981eee42e4f9fb4f6d726b97aa8122322543beNingning Xia        self.mox.StubOutWithMock(models.test, 'parse_job_keyval')
8022e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
80324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8042e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def tearDown(self):
8052e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        logging.getLogger().setLevel(self._saved_loglevel)
8062e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        super(OffloadDirectoryTests, self).tearDown()
8072e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
808b41527d6f865688299dc5250f8d58baca9432777Allen Li    def _mock__upload_cts_testresult(self):
809b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.mox.StubOutWithMock(gs_offloader, '_upload_cts_testresult')
810b41527d6f865688299dc5250f8d58baca9432777Allen Li        gs_offloader._upload_cts_testresult(
8114211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia                mox.IgnoreArg(),mox.IgnoreArg()).AndReturn(None)
81224f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8135ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    def _mock_create_marker_file(self):
8145ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.mox.StubOutWithMock(__builtin__, 'open')
8159579b38072f8008b92623d7c30e3fc55c05c7561Allen Li        open(mox.IgnoreArg(), 'a').AndReturn(mock.MagicMock())
8165ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow
8175ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow
8185ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    def _mock_offload_dir_calls(self, command, queue_args,
819b41527d6f865688299dc5250f8d58baca9432777Allen Li                                marker_initially_exists=False):
8202e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Mock out the calls needed by `offload_dir()`.
8212e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8222e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        This covers only the calls made when there is no timeout.
8232e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8242e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        @param command Command list to be returned by the mocked
825b41527d6f865688299dc5250f8d58baca9432777Allen Li                       call to `_get_cmd_list()`.
8262e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8272e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
8285ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self.mox.StubOutWithMock(os.path, 'isfile')
8295ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        os.path.isfile(mox.IgnoreArg()).AndReturn(marker_initially_exists)
830dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        command.append(queue_args[0])
831b41527d6f865688299dc5250f8d58baca9432777Allen Li        gs_offloader._get_cmd_list(
832e93c85778aa8b22aa88482c43092133d59434147MK Ryu                False, queue_args[0],
833e93c85778aa8b22aa88482c43092133d59434147MK Ryu                '%s%s' % (utils.DEFAULT_OFFLOAD_GSURI,
834e93c85778aa8b22aa88482c43092133d59434147MK Ryu                          queue_args[1])).AndReturn(command)
835b41527d6f865688299dc5250f8d58baca9432777Allen Li        self._mock__upload_cts_testresult()
8362e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
83724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8385ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow    def _run_offload_dir(self, should_succeed, delete_age):
8392e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Make one call to `offload_dir()`.
8402e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8412e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        The caller ensures all mocks are set up already.
8422e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8432e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        @param should_succeed True iff the call to `offload_dir()`
8442e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                              is expected to succeed and remove the
8452e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                              offloaded job directory.
8462e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8472e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """
8482e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.ReplayAll()
849b41527d6f865688299dc5250f8d58baca9432777Allen Li        gs_offloader.GSOffloader(
850b41527d6f865688299dc5250f8d58baca9432777Allen Li                utils.DEFAULT_OFFLOAD_GSURI, False, delete_age).offload(
851e93c85778aa8b22aa88482c43092133d59434147MK Ryu                        self._job.queue_args[0],
8525ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                        self._job.queue_args[1],
8535ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow                        self._job.queue_args[2])
8542e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.mox.VerifyAll()
8552e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        self.assertEqual(not should_succeed,
8562e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette                         os.path.isdir(self._job.queue_args[0]))
8572e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
85824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8592e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_success(self):
8602e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` can succeed correctly."""
861dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self._mock_offload_dir_calls(['test', '-d'],
862dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi                                     self._job.queue_args)
863b41527d6f865688299dc5250f8d58baca9432777Allen Li        os.path.isfile(mox.IgnoreArg()).AndReturn(True)
8645ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self._mock_create_marker_file()
8655ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self._run_offload_dir(True, 0)
8662e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
86724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
8682e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette    def test_offload_failure(self):
8692e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette        """Test that `offload_dir()` can fail correctly."""
870dd129979e8227c960f4c7a3d2a1665007f8a424eSimran Basi        self._mock_offload_dir_calls(['test', '!', '-d'],
871b41527d6f865688299dc5250f8d58baca9432777Allen Li                                     self._job.queue_args)
8725ba5fb86d92a242691def5fc87ff35e51497b2aeKeith Haddow        self._run_offload_dir(False, 0)
8732e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
8742e443efce8dc34f6db6ab566a4c8a552fd8fff2dJ. Richard Barnette
875affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi    def test_sanitize_dir(self):
876affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        """Test that folder/file name with invalid character can be corrected.
877affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        """
878affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        results_folder = tempfile.mkdtemp()
879b41527d6f865688299dc5250f8d58baca9432777Allen Li        invalid_chars = '_'.join(['[', ']', '*', '?', '#'])
880affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_files = []
881ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        invalid_folder_name = 'invalid_name_folder_%s' % invalid_chars
882affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_folder = os.path.join(
883affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                results_folder,
884ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby                invalid_folder_name)
885affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        invalid_files.append(os.path.join(
886affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                invalid_folder,
887affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                'invalid_name_file_%s' % invalid_chars))
888affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        good_folder =  os.path.join(results_folder, 'valid_name_folder')
889affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        good_file = os.path.join(good_folder, 'valid_name_file')
890affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for folder in [invalid_folder, good_folder]:
891affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            os.makedirs(folder)
892affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for f in invalid_files + [good_file]:
893affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            with open(f, 'w'):
894affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                pass
895ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        # check that broken symlinks don't break sanitization
896ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        symlink = os.path.join(invalid_folder, 'broken-link')
897ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        os.symlink(os.path.join(results_folder, 'no-such-file'),
898ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby                   symlink)
899ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        fifo1 = os.path.join(results_folder, 'test_fifo1')
900ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        fifo2 = os.path.join(good_folder, 'test_fifo2')
901ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        fifo3 = os.path.join(invalid_folder, 'test_fifo3')
902ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        invalid_fifo4_name = 'test_fifo4_%s' % invalid_chars
903ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        fifo4 = os.path.join(invalid_folder, invalid_fifo4_name)
904ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        os.mkfifo(fifo1)
905ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        os.mkfifo(fifo2)
906ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        os.mkfifo(fifo3)
907ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        os.mkfifo(fifo4)
908affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        gs_offloader.sanitize_dir(results_folder)
909affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        for _, dirs, files in os.walk(results_folder):
910affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi            for name in dirs + files:
911b41527d6f865688299dc5250f8d58baca9432777Allen Li                self.assertEqual(name, gslib.escape(name))
912affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi                for c in name:
913b41527d6f865688299dc5250f8d58baca9432777Allen Li                    self.assertFalse(c in ['[', ']', '*', '?', '#'])
914affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        self.assertTrue(os.path.exists(good_file))
915ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby
916ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertTrue(os.path.exists(fifo1))
917ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertFalse(is_fifo(fifo1))
918ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertTrue(os.path.exists(fifo2))
919ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertFalse(is_fifo(fifo2))
920ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        corrected_folder = os.path.join(
921b41527d6f865688299dc5250f8d58baca9432777Allen Li                results_folder, gslib.escape(invalid_folder_name))
922ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        corrected_fifo3 = os.path.join(
923ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby                corrected_folder,
924ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby                'test_fifo3')
925ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertFalse(os.path.exists(fifo3))
926ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertTrue(os.path.exists(corrected_fifo3))
927ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertFalse(is_fifo(corrected_fifo3))
928ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        corrected_fifo4 = os.path.join(
929b41527d6f865688299dc5250f8d58baca9432777Allen Li                corrected_folder, gslib.escape(invalid_fifo4_name))
930ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertFalse(os.path.exists(fifo4))
931ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertTrue(os.path.exists(corrected_fifo4))
932ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertFalse(is_fifo(corrected_fifo4))
933ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby
934ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        corrected_symlink = os.path.join(
935ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby                corrected_folder,
936ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby                'broken-link')
937ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertFalse(os.path.lexists(symlink))
938ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertTrue(os.path.exists(corrected_symlink))
939ca7726dfcd4b9b70a75147bad1d1c2ec66b79816Laurence Goodby        self.assertFalse(os.path.islink(corrected_symlink))
940affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi        shutil.rmtree(results_folder)
941affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi
942affb922d30a3f5e528103c0314d5f0586b7a90dcDan Shi
9431b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi    def check_limit_file_count(self, is_test_job=True):
9441b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """Test that folder with too many files can be compressed.
9451b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9461b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        @param is_test_job: True to check the method with test job result
9471b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                            folder. Set to False for special task folder.
9481b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """
9491b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        results_folder = tempfile.mkdtemp()
9501b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        host_folder = os.path.join(
9511b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                results_folder,
9521b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                'lab1-host1' if is_test_job else 'hosts/lab1-host1/1-repair')
9531b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        debug_folder = os.path.join(host_folder, 'debug')
9541b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        sysinfo_folder = os.path.join(host_folder, 'sysinfo')
9551b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        for folder in [debug_folder, sysinfo_folder]:
9561b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi            os.makedirs(folder)
9571b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi            for i in range(10):
9581b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                with open(os.path.join(folder, str(i)), 'w') as f:
9591b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                    f.write('test')
9601b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
961b41527d6f865688299dc5250f8d58baca9432777Allen Li        gs_offloader._MAX_FILE_COUNT = 100
9621b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.limit_file_count(
9631b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                results_folder if is_test_job else host_folder)
9641b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertTrue(os.path.exists(sysinfo_folder))
9651b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
966b41527d6f865688299dc5250f8d58baca9432777Allen Li        gs_offloader._MAX_FILE_COUNT = 10
9671b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        gs_offloader.limit_file_count(
9681b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi                results_folder if is_test_job else host_folder)
9691b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertFalse(os.path.exists(sysinfo_folder))
9701b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertTrue(os.path.exists(sysinfo_folder + '.tgz'))
9711b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.assertTrue(os.path.exists(debug_folder))
9721b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9731b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        shutil.rmtree(results_folder)
9741b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9751b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9761b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi    def test_limit_file_count(self):
9771b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """Test that folder with too many files can be compressed.
9781b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        """
9791b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.check_limit_file_count(is_test_job=True)
9801b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi        self.check_limit_file_count(is_test_job=False)
9811b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
9822d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
9838db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia    def test_is_valid_result(self):
9848db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        """Test _is_valid_result."""
98521922c807733cab1a86096500304aa8ae68bd897Ningning Xia        release_build = 'veyron_minnie-cheets-release/R52-8248.0.0'
98621922c807733cab1a86096500304aa8ae68bd897Ningning Xia        pfq_build = 'cyan-cheets-android-pfq/R54-8623.0.0-rc1'
98721922c807733cab1a86096500304aa8ae68bd897Ningning Xia        trybot_build = 'trybot-samus-release/R54-8640.0.0-b5092'
98821922c807733cab1a86096500304aa8ae68bd897Ningning Xia        trybot_2_build = 'trybot-samus-pfq/R54-8640.0.0-b5092'
98921922c807733cab1a86096500304aa8ae68bd897Ningning Xia        release_2_build = 'test-trybot-release/R54-8640.0.0-b5092'
9908db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertTrue(gs_offloader._is_valid_result(
9918db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
9926384c1094ddf148de5d3ff16aed1bbab077b5f26Rohit Makasana        self.assertTrue(gs_offloader._is_valid_result(
9936384c1094ddf148de5d3ff16aed1bbab077b5f26Rohit Makasana            release_build, gs_offloader.CTS_RESULT_PATTERN, 'test_that_wrapper'))
9948db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
99533e1289d9622cb2f8997eef6a8a7cef35db76233Richard Barnette            release_build, gs_offloader.CTS_RESULT_PATTERN, 'bvt-arc'))
9968db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertTrue(gs_offloader._is_valid_result(
99773cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel            release_build, gs_offloader.CTS_V2_RESULT_PATTERN, 'arc-gts'))
9988db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
9998db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            None, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
10008db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
10018db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_build, gs_offloader.CTS_RESULT_PATTERN, None))
10028db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
10038db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            pfq_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
10048db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
10058db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            trybot_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
10068db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertFalse(gs_offloader._is_valid_result(
10078db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            trybot_2_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
10088db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia        self.assertTrue(gs_offloader._is_valid_result(
10098db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia            release_2_build, gs_offloader.CTS_RESULT_PATTERN, 'arc-cts'))
101021922c807733cab1a86096500304aa8ae68bd897Ningning Xia
101121922c807733cab1a86096500304aa8ae68bd897Ningning Xia
10120c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia    def create_results_folder(self):
10130c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        """Create CTS/GTS results folders."""
10144211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        results_folder = tempfile.mkdtemp()
10154211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        host_folder = os.path.join(results_folder, 'chromeos4-row9-rack11-host22')
10164211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        debug_folder = os.path.join(host_folder, 'debug')
10174211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        sysinfo_folder = os.path.join(host_folder, 'sysinfo')
10184211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        cts_result_folder = os.path.join(
10194211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia                host_folder, 'cheets_CTS.android.dpi', 'results', 'cts-results')
102073cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel        cts_v2_result_folder = os.path.join(host_folder,
102173cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel                'cheets_CTS_N.CtsGraphicsTestCases', 'results', 'android-cts')
10222d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        gts_result_folder = os.path.join(
1023bfa63148ef62dc36e2d4b3456a4b64ae69b21172Ilja H. Friedel                host_folder, 'cheets_GTS.google.admin', 'results', 'android-gts')
10244211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        timestamp_str = '2016.04.28_01.41.44'
10252d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        timestamp_cts_folder = os.path.join(cts_result_folder, timestamp_str)
102673cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel        timestamp_cts_v2_folder = os.path.join(cts_v2_result_folder, timestamp_str)
10272d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        timestamp_gts_folder = os.path.join(gts_result_folder, timestamp_str)
10282d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10290c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        # Test results in cts_result_folder with a different time-stamp.
10300c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        timestamp_str_2 = '2016.04.28_10.41.44'
10310c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        timestamp_cts_folder_2 = os.path.join(cts_result_folder, timestamp_str_2)
10320c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10332d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        for folder in [debug_folder, sysinfo_folder, cts_result_folder,
103473cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel                       timestamp_cts_folder, timestamp_cts_folder_2,
103573cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel                       timestamp_cts_v2_folder, timestamp_gts_folder]:
10364211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia            os.makedirs(folder)
10372d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10380c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        path_pattern_pair = [(timestamp_cts_folder, gs_offloader.CTS_RESULT_PATTERN),
10390c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                             (timestamp_cts_folder_2, gs_offloader.CTS_RESULT_PATTERN),
104073cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel                             (timestamp_cts_v2_folder, gs_offloader.CTS_V2_RESULT_PATTERN),
104173cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel                             (timestamp_gts_folder, gs_offloader.CTS_V2_RESULT_PATTERN)]
10424211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
10430c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        # Create timestamp.zip file_path.
10440c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_zip_file = os.path.join(cts_result_folder, timestamp_str + '.zip')
10450c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_zip_file_2 = os.path.join(cts_result_folder, timestamp_str_2 + '.zip')
104673cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel        cts_v2_zip_file = os.path.join(cts_v2_result_folder, timestamp_str + '.zip')
10472d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia        gts_zip_file = os.path.join(gts_result_folder, timestamp_str + '.zip')
10484211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
10490c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        # Create xml file_path.
10500c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        cts_result_file = os.path.join(timestamp_cts_folder, 'testResult.xml')
105173cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel        cts_result_file_2 = os.path.join(timestamp_cts_folder_2,
105273cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel                                         'testResult.xml')
1053bfa63148ef62dc36e2d4b3456a4b64ae69b21172Ilja H. Friedel        gts_result_file = os.path.join(timestamp_gts_folder, 'test_result.xml')
105473cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel        cts_v2_result_file = os.path.join(timestamp_cts_v2_folder,
105573cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel                                         'test_result.xml')
10562d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
105773cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel        for file_path in [cts_zip_file, cts_zip_file_2, cts_v2_zip_file,
105873cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel                          gts_zip_file, cts_result_file, cts_result_file_2,
105973cf6cd0049a0eddd1cfdc3f73cbaf2d1f114577Ilja H. Friedel                          gts_result_file, cts_v2_result_file]:
10600c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            with open(file_path, 'w') as f:
10610c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                f.write('test')
10622d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10630c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        return (results_folder, host_folder, path_pattern_pair)
10642d88eec8f87da75d3ae5046ee34573562add3da8Ningning Xia
10650c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
1066b41527d6f865688299dc5250f8d58baca9432777Allen Li    def test__upload_cts_testresult(self):
1067b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test _upload_cts_testresult."""
10680c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        results_folder, host_folder, path_pattern_pair = self.create_results_folder()
10690c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10700c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        self.mox.StubOutWithMock(gs_offloader, '_upload_files')
10710c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        gs_offloader._upload_files(
10720c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn(
10730c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                ['test', '-d', host_folder])
10740c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        gs_offloader._upload_files(
10750c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn(
10760c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                ['test', '-d', host_folder])
10770c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        gs_offloader._upload_files(
10780c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            mox.IgnoreArg(), mox.IgnoreArg(), mox.IgnoreArg(), False).AndReturn(
10790c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                ['test', '-d', host_folder])
10804211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
10814211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self.mox.ReplayAll()
1082b41527d6f865688299dc5250f8d58baca9432777Allen Li        gs_offloader._upload_cts_testresult(results_folder, False)
10834211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        self.mox.VerifyAll()
10840c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        shutil.rmtree(results_folder)
10850c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10860c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10870c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia    def test_upload_files(self):
10880c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        """Test upload_files"""
10890c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        results_folder, host_folder, path_pattern_pair = self.create_results_folder()
10900c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
10910c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia        for path, pattern in path_pattern_pair:
10920c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            models.test.parse_job_keyval(mox.IgnoreArg()).AndReturn({
10930c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                'build': 'veyron_minnie-cheets-release/R52-8248.0.0',
10948db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia                'parent_job_id': 'p_id',
10958db632fba7f5cbbc4b6693a678582b13039f01c4Ningning Xia                'suite': 'arc-cts'
10960c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            })
10970c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
1098b41527d6f865688299dc5250f8d58baca9432777Allen Li            gs_offloader._get_cmd_list(
10990c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                False, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
11000c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                    ['test', '-d', path])
1101b41527d6f865688299dc5250f8d58baca9432777Allen Li            gs_offloader._get_cmd_list(
11020c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                False, mox.IgnoreArg(), mox.IgnoreArg()).AndReturn(
11030c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia                    ['test', '-d', path])
11040c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia
11050c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            self.mox.ReplayAll()
11060c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            gs_offloader._upload_files(host_folder, path, pattern, False)
11070c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            self.mox.VerifyAll()
11080c27d9befe9523e70b2d69ee353caa7b43270dbdNingning Xia            self.mox.ResetAll()
11094211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia
11104211124209fdb4469462b6e1b39433cc52b76d02Ningning Xia        shutil.rmtree(results_folder)
11111b4c7c396d5043b24d6bf65c069a85371bb00e5cDan Shi
111297d188c2d78728c69a2d71f08de210fe683d3d1eMichael Tang
111302dd066dc11876736eaf1841e6893a805febd899Dan Shi    def test_get_metrics_fields(self):
111402dd066dc11876736eaf1841e6893a805febd899Dan Shi        """Test method _get_metrics_fields."""
111502dd066dc11876736eaf1841e6893a805febd899Dan Shi        results_folder, host_folder, _ = self.create_results_folder()
111602dd066dc11876736eaf1841e6893a805febd899Dan Shi        models.test.parse_job_keyval(mox.IgnoreArg()).AndReturn({
111702dd066dc11876736eaf1841e6893a805febd899Dan Shi                'build': 'veyron_minnie-cheets-release/R52-8248.0.0',
111802dd066dc11876736eaf1841e6893a805febd899Dan Shi                'parent_job_id': 'p_id',
111902dd066dc11876736eaf1841e6893a805febd899Dan Shi                'suite': 'arc-cts'
112002dd066dc11876736eaf1841e6893a805febd899Dan Shi            })
112102dd066dc11876736eaf1841e6893a805febd899Dan Shi        try:
112202dd066dc11876736eaf1841e6893a805febd899Dan Shi            self.mox.ReplayAll()
112302dd066dc11876736eaf1841e6893a805febd899Dan Shi            self.assertEqual({'board': 'veyron_minnie-cheets',
112402dd066dc11876736eaf1841e6893a805febd899Dan Shi                              'milestone': 'R52'},
112502dd066dc11876736eaf1841e6893a805febd899Dan Shi                             gs_offloader._get_metrics_fields(host_folder))
112602dd066dc11876736eaf1841e6893a805febd899Dan Shi            self.mox.VerifyAll()
112702dd066dc11876736eaf1841e6893a805febd899Dan Shi        finally:
112802dd066dc11876736eaf1841e6893a805febd899Dan Shi            shutil.rmtree(results_folder)
112902dd066dc11876736eaf1841e6893a805febd899Dan Shi
113002dd066dc11876736eaf1841e6893a805febd899Dan Shi
1131ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass JobDirectoryOffloadTests(_TempResultsDirTestBase):
1132ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `_JobDirectory.enqueue_offload()`.
1133ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1134ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    When testing with a `days_old` parameter of 0, we use
1135ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    `set_finished()` instead of `set_expired()`.  This causes the
1136ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    job's timestamp to be set in the future.  This is done so as
1137ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    to test that when `days_old` is 0, the job is always treated
1138ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    as eligible for offload, regardless of the timestamp's value.
1139ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1140ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    Testing covers the following assertions:
1141ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     A. Each time `enqueue_offload()` is called, a message that
1142ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        includes the job's directory name will be logged using
1143ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `logging.debug()`, regardless of whether the job was
1144ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        enqueued.  Nothing else is allowed to be logged.
1145ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     B. If the job is not eligible to be offloaded,
1146b41527d6f865688299dc5250f8d58baca9432777Allen Li        `first_offload_start` and `offload_count` are 0.
1147ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     C. If the job is not eligible for offload, nothing is
1148ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        enqueued in `queue`.
1149b41527d6f865688299dc5250f8d58baca9432777Allen Li     D. When the job is offloaded, `offload_count` increments
1150ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        each time.
1151ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette     E. When the job is offloaded, the appropriate parameters are
1152ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        enqueued exactly once.
1153b41527d6f865688299dc5250f8d58baca9432777Allen Li     F. The first time a job is offloaded, `first_offload_start` is
1154ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        set to the current time.
1155b41527d6f865688299dc5250f8d58baca9432777Allen Li     G. `first_offload_start` only changes the first time that the
1156ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job is offloaded.
1157ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1158ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    The test cases below are designed to exercise all of the
1159ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    meaningful state transitions at least once.
1160ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1161ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """
1162ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1163ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1164ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(JobDirectoryOffloadTests, self).setUp()
11650880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._job = self.make_job(self.REGULAR_JOBLIST[0])
1166ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._queue = Queue.Queue()
1167ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
116824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1169ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _offload_unexpired_job(self, days_old):
1170ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make calls to `enqueue_offload()` for an unexpired job.
1171ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1172ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This method tests assertions B and C that calling
1173ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        `enqueue_offload()` has no effect.
1174ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1175ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1176b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(self._job.offload_count, 0)
1177b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(self._job.first_offload_start, 0)
1178b41527d6f865688299dc5250f8d58baca9432777Allen Li        gs_offloader._enqueue_offload(self._job, self._queue, days_old)
1179b41527d6f865688299dc5250f8d58baca9432777Allen Li        gs_offloader._enqueue_offload(self._job, self._queue, days_old)
1180ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(self._queue.empty())
1181b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(self._job.offload_count, 0)
1182b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(self._job.first_offload_start, 0)
1183ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
118424f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1185ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _offload_expired_once(self, days_old, count):
1186ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make one call to `enqueue_offload()` for an expired job.
1187ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1188ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This method tests assertions D and E regarding side-effects
1189ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        expected when a job is offloaded.
1190ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1191ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1192b41527d6f865688299dc5250f8d58baca9432777Allen Li        gs_offloader._enqueue_offload(self._job, self._queue, days_old)
1193b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(self._job.offload_count, count)
1194ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertFalse(self._queue.empty())
1195ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        v = self._queue.get_nowait()
1196ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertTrue(self._queue.empty())
11972c72dddb1d05ed43b23ebe847601d7f160a9753aJ. Richard Barnette        self.assertEqual(v, self._job.queue_args)
1198ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
119924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1200ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _offload_expired_job(self, days_old):
1201ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Make calls to `enqueue_offload()` for a just-expired job.
1202ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1203ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This method directly tests assertions F and G regarding
1204b41527d6f865688299dc5250f8d58baca9432777Allen Li        side-effects on `first_offload_start`.
1205ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1206ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1207ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        t0 = time.time()
1208ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_once(days_old, 1)
1209b41527d6f865688299dc5250f8d58baca9432777Allen Li        t1 = self._job.first_offload_start
1210ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertLessEqual(t1, time.time())
1211ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertGreaterEqual(t1, t0)
1212ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_once(days_old, 2)
1213b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(self._job.first_offload_start, t1)
1214ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_once(days_old, 3)
1215b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.assertEqual(self._job.first_offload_start, t1)
1216ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
121724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1218ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_1_no_expiration(self):
1219ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` of 0.
1220ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1221ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are
1222ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        made both before and after the job becomes expired.
1223ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1224ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1225ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(0)
1226ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(0)
1227ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(0)
1228ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
122924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1230ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_2_no_expiration(self):
1231ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` of 0.
1232ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1233ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1234ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only after the job becomes expired.
1235ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1236ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1237ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(0)
1238ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(0)
1239ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
124024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1241ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_1_with_expiration(self):
1242ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1243ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1244ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1245ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        before the job finishes, before the job expires, and after
1246ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the job expires.
1247ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1248ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1249ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1250ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(_TEST_EXPIRATION_AGE)
1251ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1252ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1253ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1254ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
125524f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1256ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_2_with_expiration(self):
1257ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1258ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1259ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1260ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        between finishing and expiration, and after the job expires.
1261ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1262ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1263ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_finished(_TEST_EXPIRATION_AGE)
1264ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1265ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1266ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1267ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
126824f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1269ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_3_with_expiration(self):
1270ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1271ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1272ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1273ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only before finishing and after expiration.
1274ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1275ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1276ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_unexpired_job(_TEST_EXPIRATION_AGE)
1277ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1278ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1279ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
128024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1281ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_case_4_with_expiration(self):
1282ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test a series of `enqueue_offload()` calls with `days_old` non-zero.
1283ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1284ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        This tests that offload works as expected if calls are made
1285ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        only after expiration.
1286ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1287ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1288ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._job.set_expired(_TEST_EXPIRATION_AGE)
1289ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offload_expired_job(_TEST_EXPIRATION_AGE)
1290ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1291ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1292ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass GetJobDirectoriesTests(_TempResultsDirTestBase):
1293ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `_JobDirectory.get_job_directories()`."""
1294ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1295ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1296ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(GetJobDirectoriesTests, self).setUp()
12970880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self.make_job_hierarchy()
12980880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        os.mkdir('not-a-job')
12990880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        open('not-a-dir', 'w').close()
1300ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
130124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1302ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _run_get_directories(self, cls, expected_list):
1303ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `get_job_directories()` for the given class.
1304ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1305ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Calls the method, and asserts that the returned list of
1306ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        directories matches the expected return value.
1307ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1308ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param expected_list Expected return value from the call.
1309ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1310ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        dirlist = cls.get_job_directories()
1311ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(set(dirlist), set(expected_list))
1312ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
131324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1314ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_get_regular_jobs(self):
1315ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `RegularJobDirectory.get_job_directories()`."""
1316ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_get_directories(job_directories.RegularJobDirectory,
13170880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette                                  self.REGULAR_JOBLIST)
1318ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
131924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1320ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_get_special_jobs(self):
1321ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test `SpecialJobDirectory.get_job_directories()`."""
1322ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._run_get_directories(job_directories.SpecialJobDirectory,
13230880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette                                  self.SPECIAL_JOBLIST)
1324ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1325ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1326ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass AddJobsTests(_TempResultsDirTestBase):
1327ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    """Tests for `Offloader._add_new_jobs()`."""
1328ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
13290880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette    MOREJOBS = ['115-fubar', '116-fubar', '117-fubar', '118-snafu']
1330ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1331ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1332ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(AddJobsTests, self).setUp()
133322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._initial_job_names = (
133422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette            set(self.REGULAR_JOBLIST) | set(self.SPECIAL_JOBLIST))
13350880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self.make_job_hierarchy()
13360880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        self._offloader = gs_offloader.Offloader(_get_options(['-a']))
133722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.StubOutWithMock(logging, 'debug')
1338ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
133924f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
134022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette    def _run_add_new_jobs(self, expected_key_set):
1341ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Basic test assertions for `_add_new_jobs()`.
1342ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1343ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Asserts the following:
1344ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The keys in the offloader's `_open_jobs` dictionary
1345ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            matches the expected set of keys.
1346ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * For every job in `_open_jobs`, the job has the expected
1347ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            directory name.
1348ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1349ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
135022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        count = len(expected_key_set) - len(self._offloader._open_jobs)
135122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        logging.debug(mox.IgnoreArg(), count)
135222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.ReplayAll()
135322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._offloader._add_new_jobs()
1354ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(expected_key_set,
1355ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                         set(self._offloader._open_jobs.keys()))
1356ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for jobkey, job in self._offloader._open_jobs.items():
1357b41527d6f865688299dc5250f8d58baca9432777Allen Li            self.assertEqual(jobkey, job.dirname)
135822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.VerifyAll()
135922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.ResetAll()
1360ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
136124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1362ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_add_jobs_empty(self):
1363ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test adding jobs to an empty dictionary.
1364ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1365ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Calls the offloader's `_add_new_jobs()`, then perform
1366ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        the assertions of `self._check_open_jobs()`.
1367ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1368ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
136922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_add_new_jobs(self._initial_job_names)
1370ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
137124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1372ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_add_jobs_non_empty(self):
1373ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Test adding jobs to a non-empty dictionary.
1374ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1375ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Calls the offloader's `_add_new_jobs()` twice; once from
1376ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        initial conditions, and then again after adding more
1377ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        directories.  After the second call, perform the assertions
1378ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        of `self._check_open_jobs()`.  Additionally, assert that
1379ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        keys added by the first call still map to their original
1380ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        job object after the second call.
1381ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1382ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
138322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_add_new_jobs(self._initial_job_names)
1384ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        jobs_copy = self._offloader._open_jobs.copy()
13850880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.MOREJOBS:
13860880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette            os.mkdir(d)
138722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._run_add_new_jobs(self._initial_job_names |
138822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette                                 set(self.MOREJOBS))
1389ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        for key in jobs_copy.keys():
1390ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self.assertIs(jobs_copy[key],
1391ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                          self._offloader._open_jobs[key])
1392ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1393ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1394ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteclass ReportingTests(_TempResultsDirTestBase):
1395b41527d6f865688299dc5250f8d58baca9432777Allen Li    """Tests for `Offloader._report_failed_jobs()`."""
1396ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1397ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def setUp(self):
1398ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        super(ReportingTests, self).setUp()
1399ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self._offloader = gs_offloader.Offloader(_get_options([]))
140016f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self.mox.StubOutWithMock(self._offloader, '_log_failed_jobs_locally')
140122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self.mox.StubOutWithMock(logging, 'debug')
1402ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
140324f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1404ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def _add_job(self, jobdir):
1405ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """Add a job to the dictionary of unfinished jobs."""
1406ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        j = self.make_job(jobdir)
1407b41527d6f865688299dc5250f8d58baca9432777Allen Li        self._offloader._open_jobs[j.dirname] = j
1408ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        return j
1409ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
141024f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
141122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette    def _expect_log_message(self, new_open_jobs, with_failures):
141222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """Mock expected logging calls.
141322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
1414b41527d6f865688299dc5250f8d58baca9432777Allen Li        `_report_failed_jobs()` logs one message with the number
141522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        of jobs removed from the open job set and the number of jobs
141622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        still remaining.  Additionally, if there are reportable
141722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        jobs, then it logs the number of jobs that haven't yet
141822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        offloaded.
141922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
142022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        This sets up the logging calls using `new_open_jobs` to
142122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        figure the job counts.  If `with_failures` is true, then
142222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        the log message is set up assuming that all jobs in
142322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        `new_open_jobs` have offload failures.
142422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
142522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        @param new_open_jobs New job set for calculating counts
142622dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette                             in the messages.
142722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        @param with_failures Whether the log message with a
142822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette                             failure count is expected.
142922dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
143022dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        """
143122dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        count = len(self._offloader._open_jobs) - len(new_open_jobs)
143222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        logging.debug(mox.IgnoreArg(), count, len(new_open_jobs))
143322dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        if with_failures:
143422dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette            logging.debug(mox.IgnoreArg(), len(new_open_jobs))
143522dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette
143624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
143733e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu    def _run_update(self, new_open_jobs):
1438b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Call `_report_failed_jobs()`.
1439ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1440ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        Initial conditions are set up by the caller.  This calls
1441b41527d6f865688299dc5250f8d58baca9432777Allen Li        `_report_failed_jobs()` once, and then checks these
1442ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        assertions:
1443ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette          * The offloader's new `_open_jobs` field contains only
1444ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            the entries in `new_open_jobs`.
1445ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1446ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        @param new_open_jobs A dictionary representing the expected
1447ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             new value of the offloader's
1448ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette                             `_open_jobs` field.
1449ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
1450ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ReplayAll()
1451b41527d6f865688299dc5250f8d58baca9432777Allen Li        self._offloader._report_failed_jobs()
1452b41527d6f865688299dc5250f8d58baca9432777Allen Li        self._offloader._remove_offloaded_jobs()
1453ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.assertEqual(self._offloader._open_jobs, new_open_jobs)
1454ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.VerifyAll()
1455ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        self.mox.ResetAll()
1456ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
145724f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
145816f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu    def _expect_failed_jobs(self, failed_jobs):
145916f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        """Mock expected call to log the failed jobs on local disk.
146016f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu
146116f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        TODO(crbug.com/686904): The fact that we have to mock an internal
146216f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        function for this test is evidence that we need to pull out the local
146316f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        file formatter in its own object in a future CL.
146416f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu
146516f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        @param failed_jobs: The list of jobs being logged as failed.
146616f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        """
146716f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._offloader._log_failed_jobs_locally(failed_jobs)
146816f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu
146916f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu
1470ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_no_jobs(self):
1471b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test `_report_failed_jobs()` with no open jobs.
1472ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
147333e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        Initial conditions are an empty `_open_jobs` list.
147433e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        Expected result is an empty `_open_jobs` list.
1475ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1476ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
147722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message({}, False)
147816f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs([])
147933e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        self._run_update({})
1480ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
148124f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1482ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_all_completed(self):
1483b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test `_report_failed_jobs()` with only complete jobs.
1484ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
148533e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        Initial conditions are an `_open_jobs` list consisting of only completed
148633e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        jobs.
148733e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        Expected result is an empty `_open_jobs` list.
1488ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1489ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
14900880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1491ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d).set_complete()
149222dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message({}, False)
149316f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs([])
149433e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        self._run_update({})
1495ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
149624f22c2fda0fac684286b168f642c7326a20fac7Jakob Juelich
1497ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    def test_none_finished(self):
1498b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test `_report_failed_jobs()` with only unfinished jobs.
1499ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
150033e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        Initial conditions are an `_open_jobs` list consisting of only
150133e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        unfinished jobs.
150233e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        Expected result is no change to the `_open_jobs` list.
1503ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1504ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette        """
15050880032b48fbcf11d50f33526f6817a78c2f17bfJ. Richard Barnette        for d in self.REGULAR_JOBLIST:
1506ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette            self._add_job(d)
150722dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        new_jobs = self._offloader._open_jobs.copy()
150822dd7487fba60c457747b478ab0822df3a6e8c64J. Richard Barnette        self._expect_log_message(new_jobs, False)
150916f9e5c9cbeadbfb030d2b2cf90c0816712d43d9Prathmesh Prabhu        self._expect_failed_jobs([])
151033e3e1ad214e6d681f64eb01835b18bb045ce463Prathmesh Prabhu        self._run_update(new_jobs)
1511ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1512ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette
1513b41527d6f865688299dc5250f8d58baca9432777Allen Liclass GsOffloaderMockTests(_TempResultsDirTestCase):
1514b41527d6f865688299dc5250f8d58baca9432777Allen Li    """Tests using mock instead of mox."""
1515b41527d6f865688299dc5250f8d58baca9432777Allen Li
1516b41527d6f865688299dc5250f8d58baca9432777Allen Li    def setUp(self):
1517b41527d6f865688299dc5250f8d58baca9432777Allen Li        super(GsOffloaderMockTests, self).setUp()
1518b41527d6f865688299dc5250f8d58baca9432777Allen Li        alarm = mock.patch('signal.alarm', return_value=0)
1519b41527d6f865688299dc5250f8d58baca9432777Allen Li        alarm.start()
1520b41527d6f865688299dc5250f8d58baca9432777Allen Li        self.addCleanup(alarm.stop)
1521b41527d6f865688299dc5250f8d58baca9432777Allen Li
1522b41527d6f865688299dc5250f8d58baca9432777Allen Li        self._saved_loglevel = logging.getLogger().getEffectiveLevel()
1523b41527d6f865688299dc5250f8d58baca9432777Allen Li        logging.getLogger().setLevel(logging.CRITICAL + 1)
1524b41527d6f865688299dc5250f8d58baca9432777Allen Li
1525b41527d6f865688299dc5250f8d58baca9432777Allen Li        self._job = self.make_job(self.REGULAR_JOBLIST[0])
1526b41527d6f865688299dc5250f8d58baca9432777Allen Li
1527b41527d6f865688299dc5250f8d58baca9432777Allen Li
1528b41527d6f865688299dc5250f8d58baca9432777Allen Li    def test_offload_timeout_early(self):
1529b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test that `offload_dir()` times out correctly.
1530b41527d6f865688299dc5250f8d58baca9432777Allen Li
1531b41527d6f865688299dc5250f8d58baca9432777Allen Li        This test triggers timeout at the earliest possible moment,
1532b41527d6f865688299dc5250f8d58baca9432777Allen Li        at the first call to set the timeout alarm.
1533b41527d6f865688299dc5250f8d58baca9432777Allen Li
1534b41527d6f865688299dc5250f8d58baca9432777Allen Li        """
1535b41527d6f865688299dc5250f8d58baca9432777Allen Li        signal.alarm.side_effect = [0, timeout_util.TimeoutError('fubar')]
1536b41527d6f865688299dc5250f8d58baca9432777Allen Li        with mock.patch.object(gs_offloader, '_upload_cts_testresult',
1537b41527d6f865688299dc5250f8d58baca9432777Allen Li                               autospec=True) as upload:
1538b41527d6f865688299dc5250f8d58baca9432777Allen Li            upload.return_value = None
1539b41527d6f865688299dc5250f8d58baca9432777Allen Li            gs_offloader.GSOffloader(
1540b41527d6f865688299dc5250f8d58baca9432777Allen Li                    utils.DEFAULT_OFFLOAD_GSURI, False, 0).offload(
1541b41527d6f865688299dc5250f8d58baca9432777Allen Li                            self._job.queue_args[0],
1542b41527d6f865688299dc5250f8d58baca9432777Allen Li                            self._job.queue_args[1],
1543b41527d6f865688299dc5250f8d58baca9432777Allen Li                            self._job.queue_args[2])
1544b41527d6f865688299dc5250f8d58baca9432777Allen Li            self.assertTrue(os.path.isdir(self._job.queue_args[0]))
1545b41527d6f865688299dc5250f8d58baca9432777Allen Li
1546b41527d6f865688299dc5250f8d58baca9432777Allen Li
1547b41527d6f865688299dc5250f8d58baca9432777Allen Li    # TODO(ayatane): This tests passes when run locally, but it fails
1548b41527d6f865688299dc5250f8d58baca9432777Allen Li    # when run on trybot.  I have no idea why, but the assert isdir
1549b41527d6f865688299dc5250f8d58baca9432777Allen Li    # fails.
1550b41527d6f865688299dc5250f8d58baca9432777Allen Li    #
1551b41527d6f865688299dc5250f8d58baca9432777Allen Li    # This test is also kind of redundant since we are using the timeout
1552b41527d6f865688299dc5250f8d58baca9432777Allen Li    # from chromite which has its own tests.
1553b41527d6f865688299dc5250f8d58baca9432777Allen Li    @unittest.skip('This fails on trybot')
1554b41527d6f865688299dc5250f8d58baca9432777Allen Li    def test_offload_timeout_late(self):
1555b41527d6f865688299dc5250f8d58baca9432777Allen Li        """Test that `offload_dir()` times out correctly.
1556b41527d6f865688299dc5250f8d58baca9432777Allen Li
1557b41527d6f865688299dc5250f8d58baca9432777Allen Li        This test triggers timeout at the latest possible moment, at
1558b41527d6f865688299dc5250f8d58baca9432777Allen Li        the call to clear the timeout alarm.
1559b41527d6f865688299dc5250f8d58baca9432777Allen Li
1560b41527d6f865688299dc5250f8d58baca9432777Allen Li        """
1561b41527d6f865688299dc5250f8d58baca9432777Allen Li        signal.alarm.side_effect = [0, 0, timeout_util.TimeoutError('fubar')]
1562b41527d6f865688299dc5250f8d58baca9432777Allen Li        with mock.patch.object(gs_offloader, '_upload_cts_testresult',
1563b41527d6f865688299dc5250f8d58baca9432777Allen Li                               autospec=True) as upload, \
1564b41527d6f865688299dc5250f8d58baca9432777Allen Li             mock.patch.object(gs_offloader, '_get_cmd_list',
1565b41527d6f865688299dc5250f8d58baca9432777Allen Li                               autospec=True) as get_cmd_list:
1566b41527d6f865688299dc5250f8d58baca9432777Allen Li            upload.return_value = None
1567b41527d6f865688299dc5250f8d58baca9432777Allen Li            get_cmd_list.return_value = ['test', '-d', self._job.queue_args[0]]
1568b41527d6f865688299dc5250f8d58baca9432777Allen Li            gs_offloader.GSOffloader(
1569b41527d6f865688299dc5250f8d58baca9432777Allen Li                    utils.DEFAULT_OFFLOAD_GSURI, False, 0).offload(
1570b41527d6f865688299dc5250f8d58baca9432777Allen Li                            self._job.queue_args[0],
1571b41527d6f865688299dc5250f8d58baca9432777Allen Li                            self._job.queue_args[1],
1572b41527d6f865688299dc5250f8d58baca9432777Allen Li                            self._job.queue_args[2])
1573b41527d6f865688299dc5250f8d58baca9432777Allen Li            self.assertTrue(os.path.isdir(self._job.queue_args[0]))
1574b41527d6f865688299dc5250f8d58baca9432777Allen Li
1575b41527d6f865688299dc5250f8d58baca9432777Allen Li
1576b41527d6f865688299dc5250f8d58baca9432777Allen Li
1577ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnetteif __name__ == '__main__':
1578ea785366f46ec4ed7a75d382e152a77aa51069d7J. Richard Barnette    unittest.main()
1579