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