10f1469bcdad11cf8bfe79ace33d28052418ecb48borenet#!/usr/bin/env python
20f1469bcdad11cf8bfe79ace33d28052418ecb48borenet#
30f1469bcdad11cf8bfe79ace33d28052418ecb48borenet# Copyright 2016 Google Inc.
40f1469bcdad11cf8bfe79ace33d28052418ecb48borenet#
50f1469bcdad11cf8bfe79ace33d28052418ecb48borenet# Use of this source code is governed by a BSD-style license that can be
60f1469bcdad11cf8bfe79ace33d28052418ecb48borenet# found in the LICENSE file.
70f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
80f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
90f1469bcdad11cf8bfe79ace33d28052418ecb48borenet"""Test utilities."""
100f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
110f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
120f1469bcdad11cf8bfe79ace33d28052418ecb48borenetimport filecmp
130f1469bcdad11cf8bfe79ace33d28052418ecb48borenetimport os
140f1469bcdad11cf8bfe79ace33d28052418ecb48borenetimport uuid
150f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
160f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
170f1469bcdad11cf8bfe79ace33d28052418ecb48borenetclass FileWriter(object):
180f1469bcdad11cf8bfe79ace33d28052418ecb48borenet  """Write files into a given directory."""
190f1469bcdad11cf8bfe79ace33d28052418ecb48borenet  def __init__(self, cwd):
200f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    self._cwd = cwd
210f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    if not os.path.exists(self._cwd):
220f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      os.makedirs(self._cwd)
230f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
240f1469bcdad11cf8bfe79ace33d28052418ecb48borenet  def mkdir(self, dname, mode=0755):
250f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    """Create the given directory with the given mode."""
260f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    dname = os.path.join(self._cwd, dname)
270f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    os.mkdir(dname)
280f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    os.chmod(dname, mode)
290f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
300f1469bcdad11cf8bfe79ace33d28052418ecb48borenet  def write(self, fname, mode=0640):
310f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    """Write the file with the given mode and random contents."""
320f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    fname = os.path.join(self._cwd, fname)
330f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    with open(fname, 'w') as f:
340f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      f.write(str(uuid.uuid4()))
350f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    os.chmod(fname, mode)
360f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
370f1469bcdad11cf8bfe79ace33d28052418ecb48borenet  def remove(self, fname):
380f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    """Remove the file."""
390f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    fname = os.path.join(self._cwd, fname)
400f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    if os.path.isfile(fname):
410f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      os.remove(fname)
420f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    else:
430f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      os.rmdir(fname)
440f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
450f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
460f1469bcdad11cf8bfe79ace33d28052418ecb48borenetdef compare_trees(test, a, b):
470f1469bcdad11cf8bfe79ace33d28052418ecb48borenet  """Compare two directory trees, assert if any differences."""
480f1469bcdad11cf8bfe79ace33d28052418ecb48borenet  def _cmp(prefix, dcmp):
490f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    # Verify that the file and directory names are the same.
500f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    test.assertEqual(len(dcmp.left_only), 0)
510f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    test.assertEqual(len(dcmp.right_only), 0)
520f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    test.assertEqual(len(dcmp.diff_files), 0)
530f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    test.assertEqual(len(dcmp.funny_files), 0)
540f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
550f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    # Verify that the files are identical.
560f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    for f in dcmp.common_files:
570f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      pathA = os.path.join(a, prefix, f)
580f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      pathB = os.path.join(b, prefix, f)
590f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      test.assertTrue(filecmp.cmp(pathA, pathB, shallow=False))
600f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      statA = os.stat(pathA)
610f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      statB = os.stat(pathB)
620f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      test.assertEqual(statA.st_mode, statB.st_mode)
630f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      with open(pathA, 'rb') as f:
640f1469bcdad11cf8bfe79ace33d28052418ecb48borenet        contentsA = f.read()
650f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      with open(pathB, 'rb') as f:
660f1469bcdad11cf8bfe79ace33d28052418ecb48borenet        contentsB = f.read()
670f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      test.assertEqual(contentsA, contentsB)
680f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
690f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    # Recurse on subdirectories.
700f1469bcdad11cf8bfe79ace33d28052418ecb48borenet    for prefix, obj in dcmp.subdirs.iteritems():
710f1469bcdad11cf8bfe79ace33d28052418ecb48borenet      _cmp(prefix, obj)
720f1469bcdad11cf8bfe79ace33d28052418ecb48borenet
730f1469bcdad11cf8bfe79ace33d28052418ecb48borenet  _cmp('', filecmp.dircmp(a, b))
74