#!/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()