普通文本  |  191行  |  8.69 KB

#!/usr/bin/env python
# Copyright (c) 2013 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Self-test for skimage.

import filecmp
import os
import subprocess
import sys
import tempfile

class BinaryNotFoundException(Exception):
    def __str__ (self):
        return ("Could not find binary!\n"
                "Did you forget to build the tools project?\n"
                "Self tests failed")

# Find a path to the binary to use. Iterates through a list of possible
# locations the binary may be.
def PickBinaryPath(base_dir):
    POSSIBLE_BINARY_PATHS = [
        'out/Debug/skimage',
        'out/Release/skimage',
        'xcodebuild/Debug/skimage',
        'xcodebuild/Release/skimage',
    ]
    for binary in POSSIBLE_BINARY_PATHS:
        binary_full_path = os.path.join(base_dir, binary)
        if (os.path.exists(binary_full_path)):
            return binary_full_path
    raise BinaryNotFoundException

# Quit early if two files have different content.
def DieIfFilesMismatch(expected, actual):
    if not filecmp.cmp(expected, actual):
        raise Exception("Error: file mismatch! expected=%s , actual=%s" % (
            expected, actual))

def test_invalid_file(file_dir, skimage_binary):
    """ Test the return value of skimage when an invalid file is decoded.
        If there is no expectation file, or the file expects a particular
        result, skimage should return nonzero indicating failure.
        If the file has no expectation, or ignore-failure is set to true,
        skimage should return zero indicating success. """
    invalid_file = os.path.join(file_dir, "skimage", "input", "bad-images",
                                "invalid.png")
    # No expectations file:
    args = [skimage_binary, "--readPath", invalid_file]
    result = subprocess.call(args)
    if 0 == result:
      raise Exception("'%s' should have reported failure!" % " ".join(args))

    # Directory holding all expectations files
    expectations_dir = os.path.join(file_dir, "skimage", "input", "bad-images")

    # Expectations file expecting a valid decode:
    incorrect_expectations = os.path.join(expectations_dir,
                                          "incorrect-results.json")
    args = [skimage_binary, "--readPath", invalid_file,
            "--readExpectationsPath", incorrect_expectations]
    result = subprocess.call(args)
    if 0 == result:
      raise Exception("'%s' should have reported failure!" % " ".join(args))

    # Empty expectations:
    empty_expectations = os.path.join(expectations_dir, "empty-results.json")
    output = subprocess.check_output([skimage_binary, "--readPath", invalid_file,
                                      "--readExpectationsPath",
                                      empty_expectations],
                                     stderr=subprocess.STDOUT)
    if not "Missing" in output:
      # Another test (in main()) tests to ensure that "Missing" does not appear
      # in the output. That test could be passed if the output changed so
      # "Missing" never appears. This ensures that an error is not missed if
      # that happens.
      raise Exception(
          "skimage output changed! This may cause other self tests to fail!")

    # Ignore failure:
    ignore_expectations = os.path.join(expectations_dir, "ignore-results.json")
    output = subprocess.check_output([skimage_binary, "--readPath", invalid_file,
                                      "--readExpectationsPath",
                                      ignore_expectations],
                                     stderr=subprocess.STDOUT)
    if not "failures" in output:
      # Another test (in main()) tests to ensure that "failures" does not
      # appear in the output. That test could be passed if the output changed
      # so "failures" never appears. This ensures that an error is not missed
      # if that happens.
      raise Exception(
          "skimage output changed! This may cause other self tests to fail!")

def test_incorrect_expectations(file_dir, skimage_binary):
    """ Test that comparing to incorrect expectations fails, unless
        ignore-failures is set to true. """
    valid_file = os.path.join(file_dir, "skimage", "input",
                                    "images-with-known-hashes",
                                    "1209453360120438698.png")
    expectations_dir = os.path.join(file_dir, "skimage", "input",
                                    "images-with-known-hashes")

    incorrect_results = os.path.join(expectations_dir,
                                     "incorrect-results.json")
    args = [skimage_binary, "--readPath", valid_file, "--readExpectationsPath",
            incorrect_results]
    result = subprocess.call(args)
    if 0 == result:
      raise Exception("'%s' should have reported failure!" % " ".join(args))

    ignore_results = os.path.join(expectations_dir, "ignore-failures.json")
    subprocess.check_call([skimage_binary, "--readPath", valid_file,
                           "--readExpectationsPath", ignore_results])

def main():
    # Use the directory of this file as the out directory
    file_dir = os.path.abspath(os.path.dirname(__file__))

    trunk_dir = os.path.normpath(os.path.join(file_dir, os.pardir, os.pardir))

    # Find the binary
    skimage_binary = PickBinaryPath(trunk_dir)
    print "Running " + skimage_binary

    # Generate an expectations file from known images.
    images_dir = os.path.join(file_dir, "skimage", "input",
                              "images-with-known-hashes")
    expectations_path = os.path.join(file_dir, "skimage", "output-actual",
                                     "create-expectations", "expectations.json")
    subprocess.check_call([skimage_binary, "--readPath", images_dir,
                           "--createExpectationsPath", expectations_path])

    # Make sure the expectations file was generated correctly.
    golden_expectations = os.path.join(file_dir, "skimage", "output-expected",
                                       "create-expectations",
                                       "expectations.json")
    DieIfFilesMismatch(expected=golden_expectations, actual=expectations_path)

    # Tell skimage to read back the expectations file it just wrote, and
    # confirm that the images in images_dir match it.
    output = subprocess.check_output([skimage_binary, "--readPath", images_dir,
                                      "--readExpectationsPath",
                                      expectations_path],
                                     stderr=subprocess.STDOUT)

    # Although skimage succeeded, it would have reported success if the file
    # was missing from the expectations file. Consider this a failure, since
    # the expectations file was created from this same image. (It will print
    # "Missing" in this case before listing the missing expectations).
    if "Missing" in output:
      raise Exception("Expectations file was missing expectations: %s" % output)

    # Again, skimage would succeed if there were known failures (and print
    # "failures"), but there should be no failures, since the file just
    # created did not include failures to ignore.
    if "failures" in output:
      raise Exception("Image failed: %s" % output)


    test_incorrect_expectations(file_dir=file_dir,
                                skimage_binary=skimage_binary)

    # Generate an expectations file from an empty directory.
    empty_dir = tempfile.mkdtemp()
    expectations_path = os.path.join(file_dir, "skimage", "output-actual",
                                     "empty-dir", "expectations.json")
    subprocess.check_call([skimage_binary, "--readPath", empty_dir,
                           "--createExpectationsPath", expectations_path])
    golden_expectations = os.path.join(file_dir, "skimage", "output-expected",
                                       "empty-dir", "expectations.json")
    DieIfFilesMismatch(expected=golden_expectations, actual=expectations_path)
    os.rmdir(empty_dir)

    # Generate an expectations file from a nonexistent directory.
    expectations_path = os.path.join(file_dir, "skimage", "output-actual",
                                     "nonexistent-dir", "expectations.json")
    subprocess.check_call([skimage_binary, "--readPath", "/nonexistent/dir",
                           "--createExpectationsPath", expectations_path])
    golden_expectations = os.path.join(file_dir, "skimage", "output-expected",
                                       "nonexistent-dir", "expectations.json")
    DieIfFilesMismatch(expected=golden_expectations, actual=expectations_path)

    test_invalid_file(file_dir=file_dir, skimage_binary=skimage_binary)

    # Done with all tests.
    print "Self tests succeeded!"

if __name__ == "__main__":
    main()