Home | History | Annotate | Download | only in platform_TLSDate
      1 # Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
      2 # Use of this source code is governed by a BSD-style license that can be
      3 # found in the LICENSE file.
      4 
      5 import logging
      6 import os
      7 import pwd
      8 import subprocess
      9 import tempfile
     10 
     11 from autotest_lib.client.bin import test
     12 from autotest_lib.client.common_lib import error
     13 
     14 class TLSDate:
     15     """
     16     A single tlsdate invocation. Takes care of setting up a temporary cachedir
     17     for it, along with collecting output from both it and its helper processes.
     18     """
     19     def __init__(self, test_obj):
     20         self._proc = None
     21         self._testdir = tempfile.mkdtemp(suffix='tlsdate')
     22         self._cachedir = self._testdir + '/cache'
     23         self._outfile = self._testdir + '/out'
     24         self._subprog = '?'
     25         self._test_obj = test_obj
     26         self._output = None
     27         self._tlsdate_uid = pwd.getpwnam('tlsdate').pw_uid
     28         os.mkdir(self._cachedir)
     29         # Let the tlsdate user (tlsdate) write.
     30         os.chown(self._testdir, self._tlsdate_uid, -1)
     31         # Allow support shell library to be sourced.
     32         os.chown(self._test_obj.srcdir + '/time.sh', self._tlsdate_uid, -1)
     33 
     34 
     35     def start(self, subprog):
     36         logging.info('running with %s/%s', self._test_obj.srcdir, subprog)
     37         self._subprog = subprog
     38         # Make sure the tlsdate user can access the files
     39         fake_tlsdate = self._test_obj.srcdir + '/' + subprog
     40         os.chown(fake_tlsdate, self._tlsdate_uid, -1)
     41         args = ['/usr/bin/tlsdated', '-p',
     42                 '-f', self._test_obj.srcdir + '/test.conf',
     43                 '-c', self._cachedir,
     44                 '-v',
     45                 fake_tlsdate,
     46                 self._outfile]
     47         self._proc = subprocess.Popen(args, stdin=subprocess.PIPE,
     48                                       stderr=subprocess.PIPE)
     49 
     50 
     51     def route_up(self):
     52         self._proc.stdin.write('n')
     53         self._proc.stdin.flush()
     54 
     55 
     56     def kill(self):
     57         self._proc.terminate()
     58 
     59 
     60     def output(self):
     61         if not self._output:
     62             self._output = self._proc.communicate()[1].split('\n')
     63         return self._output
     64 
     65 
     66     def in_output(self, string):
     67         for x in self.output():
     68             if string in x:
     69                 return True
     70         return False
     71 
     72 
     73     def subproc_output(self):
     74         with open(self._outfile) as f:
     75             return [x.rstrip() for x in f.readlines()]
     76 
     77 
     78     def ok(self):
     79         return 'ok' in self.subproc_output()
     80 
     81 
     82 class platform_TLSDate(test.test):
     83     version = 1
     84 
     85     def require_ok(self, t):
     86         if not t.ok():
     87             raise error.TestFail('Expected success, got:' +
     88                                  ';'.join(t.subproc_output()))
     89 
     90 
     91     def require_output(self, t, string):
     92         if not t.in_output(string):
     93             raise error.TestFail('Needed "%s" but got "%s"' % (string,
     94                                  ';'.join(t.output())))
     95 
     96 
     97     def require_not_output(self, t, string):
     98         if t.in_output(string):
     99             raise error.TestFail('Needed no "%s" but got "%s"' % (string,
    100                                  ';'.join(t.output())))
    101 
    102 
    103     def test_delay_subproc(self):
    104         """
    105         Tests that a subprocess that delays for one second is waited on
    106         successfully the second time.
    107         """
    108         t = TLSDate(self)
    109         t.start('delay_subproc')
    110         self.require_output(t, 'attempt 1 backoff')
    111         self.require_output(t, 'time set from the network')
    112         self.require_ok(t)
    113 
    114 
    115     def test_hang_subproc(self):
    116         """
    117         Tests that a subprocess that delays for too long is considered hung and
    118         killed.
    119         """
    120         t = TLSDate(self)
    121         t.start('hang_subproc')
    122         self.require_output(t, 'attempt 1 backoff')
    123         self.require_output(t, 'tlsdate timed out')
    124         self.require_ok(t)
    125 
    126 
    127     def test_fail_routes(self):
    128         """
    129         Tests that if the initial tlsdate call fails, we wait for a route to
    130         appear, then rerun tlsdate.
    131         """
    132         t = TLSDate(self)
    133         t.start('fail_routes')
    134         t.route_up()
    135         self.require_output(t, 'status:2')
    136         self.require_output(t, 'stdin')
    137         self.require_output(t, 'time set from the network')
    138         self.require_ok(t)
    139 
    140 
    141     def run_once(self):
    142         self.test_delay_subproc()
    143         self.test_hang_subproc()
    144         self.test_fail_routes()
    145