Home | History | Annotate | Download | only in tests
      1 #!/usr/bin/env python
      2 # Copyright (c) 2013 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 # Self-test for skimage.
      7 
      8 import filecmp
      9 import os
     10 import subprocess
     11 import sys
     12 import tempfile
     13 
     14 class BinaryNotFoundException(Exception):
     15     def __str__ (self):
     16         return ("Could not find binary!\n"
     17                 "Did you forget to build the tools project?\n"
     18                 "Self tests failed")
     19 
     20 # Find a path to the binary to use. Iterates through a list of possible
     21 # locations the binary may be.
     22 def PickBinaryPath(base_dir):
     23     POSSIBLE_BINARY_PATHS = [
     24         'out/Debug/skimage',
     25         'out/Release/skimage',
     26         'xcodebuild/Debug/skimage',
     27         'xcodebuild/Release/skimage',
     28     ]
     29     for binary in POSSIBLE_BINARY_PATHS:
     30         binary_full_path = os.path.join(base_dir, binary)
     31         if (os.path.exists(binary_full_path)):
     32             return binary_full_path
     33     raise BinaryNotFoundException
     34 
     35 # Quit early if two files have different content.
     36 def DieIfFilesMismatch(expected, actual):
     37     if not filecmp.cmp(expected, actual):
     38         print 'Error: file mismatch! expected=%s , actual=%s' % (
     39             expected, actual)
     40         exit(1)
     41 
     42 def test_invalid_file(file_dir, skimage_binary):
     43     """ Test the return value of skimage when an invalid file is decoded.
     44         If there is no expectation file, or the file expects a particular
     45         result, skimage should return nonzero indicating failure.
     46         If the file has no expectation, or ignore-failure is set to true,
     47         skimage should return zero indicating success. """
     48     invalid_file = os.path.join(file_dir, "skimage", "input", "bad-images",
     49                                 "invalid.png")
     50     # No expectations file:
     51     args = [skimage_binary, "--readPath", invalid_file]
     52     result = subprocess.call(args)
     53     if 0 == result:
     54       print "'%s' should have reported failure!" % " ".join(args)
     55       exit(1)
     56 
     57     # Directory holding all expectations files
     58     expectations_dir = os.path.join(file_dir, "skimage", "input", "bad-images")
     59 
     60     # Expectations file expecting a valid decode:
     61     incorrect_expectations = os.path.join(expectations_dir,
     62                                           "incorrect-results.json")
     63     args = [skimage_binary, "--readPath", invalid_file,
     64             "--readExpectationsPath", incorrect_expectations]
     65     result = subprocess.call(args)
     66     if 0 == result:
     67       print "'%s' should have reported failure!" % " ".join(args)
     68       exit(1)
     69 
     70     # Empty expectations:
     71     empty_expectations = os.path.join(expectations_dir, "empty-results.json")
     72     output = subprocess.check_output([skimage_binary, "--readPath", invalid_file,
     73                                       "--readExpectationsPath",
     74                                       empty_expectations],
     75                                      stderr=subprocess.STDOUT)
     76     if not "Missing" in output:
     77       # Another test (in main()) tests to ensure that "Missing" does not appear
     78       # in the output. That test could be passed if the output changed so
     79       # "Missing" never appears. This ensures that an error is not missed if
     80       # that happens.
     81       print "skimage output changed! This may cause other self tests to fail!"
     82       exit(1)
     83 
     84     # Ignore failure:
     85     ignore_expectations = os.path.join(expectations_dir, "ignore-results.json")
     86     output = subprocess.check_output([skimage_binary, "--readPath", invalid_file,
     87                                       "--readExpectationsPath",
     88                                       ignore_expectations],
     89                                      stderr=subprocess.STDOUT)
     90     if not "failures" in output:
     91       # Another test (in main()) tests to ensure that "failures" does not
     92       # appear in the output. That test could be passed if the output changed
     93       # so "failures" never appears. This ensures that an error is not missed
     94       # if that happens.
     95       print "skimage output changed! This may cause other self tests to fail!"
     96       exit(1)
     97 
     98 def test_incorrect_expectations(file_dir, skimage_binary):
     99     """ Test that comparing to incorrect expectations fails, unless
    100         ignore-failures is set to true. """
    101     valid_file = os.path.join(file_dir, "skimage", "input",
    102                                     "images-with-known-hashes",
    103                                     "1209453360120438698.png")
    104     expectations_dir = os.path.join(file_dir, "skimage", "input",
    105                                     "images-with-known-hashes")
    106 
    107     incorrect_results = os.path.join(expectations_dir,
    108                                      "incorrect-results.json")
    109     args = [skimage_binary, "--readPath", valid_file, "--readExpectationsPath",
    110             incorrect_results]
    111     result = subprocess.call(args)
    112     if 0 == result:
    113       print "'%s' should have reported failure!" % " ".join(args)
    114       exit(1)
    115 
    116     ignore_results = os.path.join(expectations_dir, "ignore-failures.json")
    117     subprocess.check_call([skimage_binary, "--readPath", valid_file,
    118                            "--readExpectationsPath", ignore_results])
    119 
    120 def main():
    121     # Use the directory of this file as the out directory
    122     file_dir = os.path.abspath(os.path.dirname(__file__))
    123 
    124     trunk_dir = os.path.normpath(os.path.join(file_dir, os.pardir, os.pardir))
    125 
    126     # Find the binary
    127     skimage_binary = PickBinaryPath(trunk_dir)
    128     print "Running " + skimage_binary
    129 
    130     # Generate an expectations file from known images.
    131     images_dir = os.path.join(file_dir, "skimage", "input",
    132                               "images-with-known-hashes")
    133     expectations_path = os.path.join(file_dir, "skimage", "output-actual",
    134                                      "create-expectations", "expectations.json")
    135     subprocess.check_call([skimage_binary, "--readPath", images_dir,
    136                            "--createExpectationsPath", expectations_path])
    137 
    138     # Make sure the expectations file was generated correctly.
    139     golden_expectations = os.path.join(file_dir, "skimage", "output-expected",
    140                                        "create-expectations",
    141                                        "expectations.json")
    142     DieIfFilesMismatch(expected=golden_expectations, actual=expectations_path)
    143 
    144     # Tell skimage to read back the expectations file it just wrote, and
    145     # confirm that the images in images_dir match it.
    146     output = subprocess.check_output([skimage_binary, "--readPath", images_dir,
    147                                       "--readExpectationsPath",
    148                                       expectations_path],
    149                                      stderr=subprocess.STDOUT)
    150 
    151     # Although skimage succeeded, it would have reported success if the file
    152     # was missing from the expectations file. Consider this a failure, since
    153     # the expectations file was created from this same image. (It will print
    154     # "Missing" in this case before listing the missing expectations).
    155     if "Missing" in output:
    156       print "Expectations file was missing expectations!"
    157       print output
    158       exit(1)
    159 
    160     # Again, skimage would succeed if there were known failures (and print
    161     # "failures"), but there should be no failures, since the file just
    162     # created did not include failures to ignore.
    163     if "failures" in output:
    164       print "Image failed!"
    165       print output
    166       exit(1)
    167 
    168 
    169     test_incorrect_expectations(file_dir=file_dir,
    170                                 skimage_binary=skimage_binary)
    171 
    172     # Generate an expectations file from an empty directory.
    173     empty_dir = tempfile.mkdtemp()
    174     expectations_path = os.path.join(file_dir, "skimage", "output-actual",
    175                                      "empty-dir", "expectations.json")
    176     subprocess.check_call([skimage_binary, "--readPath", empty_dir,
    177                            "--createExpectationsPath", expectations_path])
    178     golden_expectations = os.path.join(file_dir, "skimage", "output-expected",
    179                                        "empty-dir", "expectations.json")
    180     DieIfFilesMismatch(expected=golden_expectations, actual=expectations_path)
    181     os.rmdir(empty_dir)
    182 
    183     # Generate an expectations file from a nonexistent directory.
    184     expectations_path = os.path.join(file_dir, "skimage", "output-actual",
    185                                      "nonexistent-dir", "expectations.json")
    186     subprocess.check_call([skimage_binary, "--readPath", "/nonexistent/dir",
    187                            "--createExpectationsPath", expectations_path])
    188     golden_expectations = os.path.join(file_dir, "skimage", "output-expected",
    189                                        "nonexistent-dir", "expectations.json")
    190     DieIfFilesMismatch(expected=golden_expectations, actual=expectations_path)
    191 
    192     test_invalid_file(file_dir=file_dir, skimage_binary=skimage_binary)
    193 
    194     # Done with all tests.
    195     print "Self tests succeeded!"
    196 
    197 if __name__ == "__main__":
    198     main()
    199