diff options
author | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
---|---|---|
committer | initial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-07-26 23:55:29 +0000 |
commit | 09911bf300f1a419907a9412154760efd0b7abc3 (patch) | |
tree | f131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/tools/test | |
parent | 586acc5fe142f498261f52c66862fa417c3d52d2 (diff) | |
download | chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.zip chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.gz chromium_src-09911bf300f1a419907a9412154760efd0b7abc3.tar.bz2 |
Add chrome to the repository.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@15 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/tools/test')
-rw-r--r-- | chrome/tools/test/generate_mime_tests.pl | 270 | ||||
-rw-r--r-- | chrome/tools/test/image_diff/SConscript | 106 | ||||
-rw-r--r-- | chrome/tools/test/image_diff/image_diff.cc | 291 | ||||
-rw-r--r-- | chrome/tools/test/image_diff/image_diff.vcproj | 49 | ||||
-rw-r--r-- | chrome/tools/test/smoketests.py | 263 |
5 files changed, 979 insertions, 0 deletions
diff --git a/chrome/tools/test/generate_mime_tests.pl b/chrome/tools/test/generate_mime_tests.pl new file mode 100644 index 0000000..1446b85 --- /dev/null +++ b/chrome/tools/test/generate_mime_tests.pl @@ -0,0 +1,270 @@ +#!/usr/bin/perl -w +# Copyright 2008, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# Generate html files that will be used test MIME type handling using +# the layout test framework. + +use strict; +use Switch; # used for switch-case program structure + +my $arg_count = $#ARGV + 1; + +# Make sure that only one command line argument is provided +if ($arg_count ne 1) { + print "Usage:\n generate_mime_tests.pl < target_path >\n target_path". + " - path where the generated tests are to be placed"; + exit; +} + +# Obtain target path from the command line +my $target_path = $ARGV[0]; + +# Set relative path of the page to be requested +my $root = "resources/getpage.pl?"; + +# Variables used in the script +my $content_type; +my $parameter; +my $source; # Temporary variable to hold source path +my $count; # Used to generate number appended to filenames +my $current_expected = ""; # Temporary storage for expected result +my $query_description; + +# Number of tests each content type goes through, also determines the half +# size of the expected results matrix +my $test_set_size = 14; + +# List of HTTP content types to be used in generating test HTMLs +my @content_type = ("NULL", + "text/plain", + "text/html", + "image/gif", + "image/bmp", + "image/tif", + "image/png", + "image/jpg", + "application/x-shockwave-flash"); + +# List of URL query parameters to be used in generating test HTMLs +my @parameter = ("tag=img&content=type_gif.gif", + "tag=img&content=type_bmp.bmp", + "tag=img&content=type_tif.tif", + "tag=img&content=type_png.png", + "tag=img&content=type_jpg.jpg", + "tag=img&content=type_txt.txt", + "tag=embed&content=type_swf.swf", + "switch=nohtml&content=type_gif.gif", + "switch=nohtml&content=type_bmp.bmp", + "switch=nohtml&content=type_tif.tif", + "switch=nohtml&content=type_png.png", + "switch=nohtml&content=type_jpg.jpg", + "switch=nohtml&content=type_txt.txt", + "switch=nohtml&content=type_swf.swf"); + +# Matrix with expected results of all tests. +# The matrix rows have four parts +# 1. iframe with a html +# 2. iframe without a html +# 3. content within a html page +# 4. content without a html +# Each part has the same sequence of column headers +my @expected = ( +# gif bmp tif png jpg txt swf +# gif bmp tif png jpg txt swf +# gif bmp tif png jpg txt swf +# gif bmp tif png jpg txt swf + # NULL + "html","html","html","html","html","html","html", # iframe html + "void","void","image","void","void", "text","text", # iframe no html + "html","html","html","html","html","html","html", # html + "image","void","image","image","image","text","text", # no html + + # text/plain + "html","html","html","html","html","html","html", # iframe html + "void","void","image","void","void", "text","text", # iframe no html + "html","html","html","html","html","html","html", # html + "image","void","image","image","image","text","text", # no html + + # text/html + "rs", "rf", "rf", "rs", "rs", "rf", "rs", # iframe html + "text","text","text","text", "text", "text","text", # iframe no html + "rs", "rf", "rf", "rs", "rs", "rf", "rs", # html + "text", "text","text", "text", "text", "text","text", # no html + + # image/gif + "void","void","void","void","void","void","void", # iframe html + "void","void","void","void", "void", "void","void", # iframe no html + "void","void","void","void","void","void","void", # html + "image","void","void", "image","image","void","void", # no html + + # image/bmp + "void","void","void","void","void","void","void", # iframe html + "void","void","void","void", "void", "void","void", # iframe no html + "void","void","void","void","void","void","void", # html + "image","void","void", "image","image","void","void", # no html + + # image/tif + "void","void","void","void","void","void","void", # iframe html + "void","void","void","void", "void", "void","void", # iframe no html + "void","void","void","void","void","void","void", # html + "void", "void","void", "void", "void", "void","void", # no html + + # image/png + "void","void","void","void","void","void","void", # iframe html + "void","void","void","void", "void", "void","void", # iframe no html + "void","void","void","void","void","void","void", # html + "image","void","void", "image","image","void","void", # no html + + # image/jpg + "void","void","void","void","void","void","void", # iframe html + "void","void","void","void", "void", "void","void", # iframe no html + "void","void","void","void","void","void","void", # html + "image","void","void", "image","void", "void","void", # no html + + # application/x-shockwave-flash + "void","void","void","void","void","void","void", # iframe html + "flash","void","void","flash","flash","void","flash", # iframe no html + "void","void","void","void","void","void","void", # html + "flash","void","void", "flash","flash","void","flash");# no html + +# get_description() +# Maps the expected word to an appropriate phrase. +# Used to generated verbal descriptions for expected results of every test. +# Input : expected result from the matrix +# Output : returns the associated description +sub get_result_description +{ + switch ($_[0]) { + case "void" { return "NOTHING";} + case "image" { return "an IMAGE";} + case "text" { return "simple TEXT";} + case "html" { return "an HTML as text";} + case "flash" { return "a FLASH object"} + case "rs" { return "been RENDERED CORRECTLY";} + case "rf" { return "been RENDERED INCORRECTLY";} + else { return "UNKNOWN";} + } +} + +# get_query_description() +# Maps the URL query to an appropriate phrase. +# Used to generated verbal descriptions for URL queries of every test. +# Input : URL query +# Output : returns the associated description +sub get_query_description +{ + switch ($_[0]) { + case "tag=img&content=type_gif.gif" { return "HTML page with a GIF image";} + case "tag=img&content=type_bmp.bmp" { return "HTML page with a BMP image";} + case "tag=img&content=type_tif.tif" { return "HTML page with a TIF image";} + case "tag=img&content=type_png.png" { return "HTML page with a PNG image";} + case "tag=img&content=type_jpg.jpg" { return "HTML page with a JPEG image"} + case "tag=img&content=type_txt.txt" { return "HTML page";} + case "tag=embed&content=type_swf.swf" { return "an HTML page with a FLASH object";} + case "switch=nohtml&content=type_gif.gif" { return "GIF image and no HTML";} + case "switch=nohtml&content=type_bmp.bmp" { return "BMP image and no HTML";} + case "switch=nohtml&content=type_tif.tif" { return "TIF image and no HTML";} + case "switch=nohtml&content=type_png.png" { return "PNG image and no HTML";} + case "switch=nohtml&content=type_jpg.jpg" { return "JPEG image and no HTML"} + case "switch=nohtml&content=type_txt.txt" { return "simple TEXT and no HTML";} + case "switch=nohtml&content=type_swf.swf" { return "FLASH object and no HTML";} + else { return "UNKNOWN TYPE";} + } +} + +# This loop generates one HTML page with multiple iframes in it. +# Generated one iframe for every parameter of every content type. +my $iframe_index = 0; +foreach $content_type ( @content_type) { + my $infile = join "", "iframe/", $content_type, ".html"; + $infile =~ tr/\//_/; + $infile = $target_path.$infile; + + open OUT, "> $infile" or die "Failed to open file $infile"; + print OUT "This HTML is used to test HTTP content-type \"$content_type\"". + " by having multiple iframes render different types of content for the". + " same HTTP content-type header.\n"; + print OUT "<script>\n if(window.layoutTestController)\n " . + "window.layoutTestController.waitUntilDone();\n</script>\n"; + print OUT "<html>\n<body>\n<br>Well here are the frames !<br>\n"; + + foreach $parameter ( @parameter ) { + + # Make sure to iterate only through the first half of the expected + # results matrix + if (($iframe_index > 0) && (0 == ($iframe_index % $test_set_size))) { + $iframe_index += $test_set_size; + } + $current_expected = get_result_description($expected[$iframe_index++]); + + $source = join "", $root, "type=", $content_type, "&", $parameter; + $query_description = get_query_description($parameter); + print OUT "<br><br>This frame tests loading of a $query_description when the ". + "HTTP content-type is set to \"$content_type\" .<br> Expected : This ", + "iframe should have $current_expected .<br>\n<iframe src=\"$source\" ". + "height=\"300\" width=\"500\"></iframe>\n\n"; + } + + print OUT "</body>\n</html>\n"; + print OUT "<script>\n if(window.layoutTestController)\n ". + "layoutTestController.notifyDone();\n</script>"; + close OUT; +} + +# This loop generates one HTML for every combination of content-type and +# parameter. +my $main_index = 0; +foreach $content_type ( @content_type) { + $count = 0; + foreach $parameter ( @parameter ) { + $count++; + + # Make sure to iterate only through the second half of the expected + # results matrix + if (0 == ($main_index % $test_set_size)) { + $main_index += $test_set_size; + } + + $current_expected = get_result_description($expected[$main_index++]); + + my $infile = join "", "main/", $content_type, $count, ".html"; + $infile =~ tr/\//_/; + $source = join "", $root, "type=", $content_type, "&", $parameter; + $infile = $target_path.$infile; + $query_description = get_query_description($parameter); + + open OUT, "> $infile" or die "Failed to open file $infile"; + print OUT "This tests loading of a $query_description when the HTTP content-type". + " is set to \"$content_type\" .\n Expected : This page should have ". + "$current_expected .\n\n"; + print OUT "<script>\n window.location=\"$source\";\n</script>\n"; + close OUT; + } +}
\ No newline at end of file diff --git a/chrome/tools/test/image_diff/SConscript b/chrome/tools/test/image_diff/SConscript new file mode 100644 index 0000000..7a6b825 --- /dev/null +++ b/chrome/tools/test/image_diff/SConscript @@ -0,0 +1,106 @@ +# Copyright 2008, Google Inc.
+# All rights reserved.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+# * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+# * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+Import('env_test')
+
+env_test = env_test.Clone()
+
+env_test.Prepend(
+ CPPDEFINES = [
+ 'PNG_USER_CONFIG',
+ 'CHROME_PNG_WRITE_SUPPORT',
+ '_DEBUG',
+ 'CERT_CHAIN_PARA_HAS_EXTRA_FIELDS',
+ 'WIN32_LEAN_AND_MEAN',
+ ],
+ CPPPATH = [
+ '$ZLIB_DIR',
+ '$LIBPNG_DIR',
+ '#/..',
+ ],
+ LINKFLAGS = [
+ '/INCREMENTAL',
+ '/DEBUG',
+
+ '/DELAYLOAD:"dwmapi.dll"',
+ '/DELAYLOAD:"uxtheme.dll"',
+
+ '/SUBSYSTEM:CONSOLE',
+
+ '/MACHINE:X86',
+ '/FIXED:No',
+
+ '/safeseh',
+ '/dynamicbase',
+ '/ignore:4199',
+ '/nxcompat',
+ ],
+ LIBS = [
+ 'wininet.lib',
+ 'version.lib',
+ 'msimg32.lib',
+ 'ws2_32.lib',
+ 'usp10.lib',
+ 'psapi.lib',
+ 'kernel32.lib',
+ 'user32.lib',
+ 'gdi32.lib',
+ 'winspool.lib',
+ 'comdlg32.lib',
+ 'advapi32.lib',
+ 'shell32.lib',
+ 'ole32.lib',
+ 'oleaut32.lib',
+ 'uuid.lib',
+ 'odbc32.lib',
+ 'odbccp32.lib',
+
+ 'DelayImp.lib',
+ ],
+)
+
+input_files = [
+ 'image_diff.cc',
+]
+
+libs = [
+ '$SKIA_DIR/skia.lib',
+ '$LIBPNG_DIR/libpng.lib',
+ '$BASE_DIR/gfx/base_gfx.lib',
+ '$ICU38_DIR/icuuc.lib',
+ '$ZLIB_DIR/zlib.lib',
+ '$BASE_DIR/base.lib',
+]
+
+exe = env_test.Program(['image_diff',
+ 'image_diff.pdb'],
+ input_files + libs)
+i = env_test.Install('$TARGET_ROOT', exe)
+
+env_test.Alias('chrome', i)
diff --git a/chrome/tools/test/image_diff/image_diff.cc b/chrome/tools/test/image_diff/image_diff.cc new file mode 100644 index 0000000..a2135e9 --- /dev/null +++ b/chrome/tools/test/image_diff/image_diff.cc @@ -0,0 +1,291 @@ +// Copyright 2008, Google Inc. +// All rights reserved. +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are +// met: +// +// * Redistributions of source code must retain the above copyright +// notice, this list of conditions and the following disclaimer. +// * Redistributions in binary form must reproduce the above +// copyright notice, this list of conditions and the following disclaimer +// in the documentation and/or other materials provided with the +// distribution. +// * Neither the name of Google Inc. nor the names of its +// contributors may be used to endorse or promote products derived from +// this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +// This file input format is based loosely on +// WebKitTools/DumpRenderTree/ImageDiff.m + +// The exact format of this tool's output to stdout is important, to match +// what the run-webkit-tests script expects. + +#include <algorithm> +#include <vector> + +#include "base/basictypes.h" +#include "base/command_line.h" +#include "base/gfx/png_decoder.h" +#include "base/logging.h" +#include "base/scoped_ptr.h" + +// Causes the app to remain open, waiting for pairs of filenames on stdin. +// The caller is then responsible for terminating this app. +static const wchar_t kOptionPollStdin[] = L"use-stdin"; + +// Return codes used by this utility. +static const int kStatusSame = 0; +static const int kStatusDifferent = 1; +static const int kStatusError = 2; + +class Image { + public: + Image() : w_(0), h_(0) { + } + + bool has_image() const { + return w_ > 0 && h_ > 0; + } + + int w() const { + return w_; + } + + int h() const { + return h_; + } + + // Creates the image from stdin with the given data length. On success, it + // will return true. On failure, no other methods should be accessed. + bool CreateFromStdin(int byte_length) { + if (byte_length <= 0) + return false; + + scoped_array<unsigned char> source(new unsigned char[byte_length]); + if (fread(source.get(), 1, byte_length, stdin) != byte_length) + return false; + + if (!PNGDecoder::Decode(source.get(), byte_length, PNGDecoder::FORMAT_RGBA, + &data_, &w_, &h_)) { + Clear(); + return false; + } + return true; + } + + // Creates the image from the given filename on disk, and returns true on + // success. + bool CreateFromFilename(const char* filename) { + FILE* f; + if (fopen_s(&f, filename, "rb") != 0) + return false; + + std::vector<unsigned char> compressed; + const int buf_size = 1024; + unsigned char buf[buf_size]; + size_t num_read = 0; + while ((num_read = fread(buf, 1, buf_size, f)) > 0) { + std::copy(buf, &buf[num_read], std::back_inserter(compressed)); + } + + fclose(f); + + if (!PNGDecoder::Decode(&compressed[0], compressed.size(), + PNGDecoder::FORMAT_RGBA, &data_, &w_, &h_)) { + Clear(); + return false; + } + return true; + } + + void Clear() { + w_ = h_ = 0; + data_.clear(); + } + + // Returns the RGBA value of the pixel at the given location + uint32 pixel_at(int x, int y) const { + DCHECK(x >= 0 && x < w_); + DCHECK(y >= 0 && y < h_); + return data_[(y * w_ + x) * 4]; + } + + private: + // pixel dimensions of the image + int w_, h_; + + std::vector<unsigned char> data_; +}; + +float PercentageDifferent(const Image& baseline, const Image& actual) { + int w = std::min(baseline.w(), actual.w()); + int h = std::min(baseline.h(), actual.h()); + + // compute pixels different in the overlap + int pixels_different = 0; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + if (baseline.pixel_at(x, y) != actual.pixel_at(x, y)) + pixels_different++; + } + } + + // count pixels that are a difference in size as also being different + int max_w = std::max(baseline.w(), actual.w()); + int max_h = std::max(baseline.h(), actual.h()); + + // ...pixels off the right side, but not including the lower right corner + pixels_different += (max_w - w) * h; + + // ...pixels along the bottom, including the lower right corner + pixels_different += (max_h - h) * max_w; + + // Like the WebKit ImageDiff tool, we define percentage different in terms + // of the size of the 'actual' bitmap. + float total_pixels = static_cast<float>(actual.w()) * + static_cast<float>(actual.h()); + if (total_pixels == 0) + return 100.0f; // when the bitmap is empty, they are 100% different + return static_cast<float>(pixels_different) / total_pixels * 100; +} + +void PrintHelp() { + fprintf(stderr, + "Usage:\n" + " image_diff <compare file> <reference file>\n" + " Compares two files on disk, returning 0 when they are the same\n" + " image_diff --use-stdin\n" + " Stays open reading pairs of filenames from stdin, comparing them,\n" + " and sending 0 to stdout when they are the same\n"); + /* For unfinished webkit-like-mode (see below) + "\n" + " image_diff -s\n" + " Reads stream input from stdin, should be EXACTLY of the format\n" + " \"Content-length: <byte length> <data>Content-length: ...\n" + " it will take as many file pairs as given, and will compare them as\n" + " (cmp_file, reference_file) pairs\n"); + */ +} + +int CompareImages(const char* file1, const char* file2) { + Image actual_image; + Image baseline_image; + + if (!actual_image.CreateFromFilename(file1)) { + fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file1); + return kStatusError; + } + if (!baseline_image.CreateFromFilename(file2)) { + fprintf(stderr, "image_diff: Unable to open file \"%s\"\n", file2); + return kStatusError; + } + + float percent = PercentageDifferent(actual_image, baseline_image); + if (percent > 0.0) { + // failure: The WebKit version also writes the difference image to + // stdout, which seems excessive for our needs. + printf("diff: %01.2f%% failed\n", percent); + return kStatusDifferent; + } + + // success + printf("diff: %01.2f%% passed\n", percent); + return kStatusSame; + +/* Untested mode that acts like WebKit's image comparator. I wrote this but + decided it's too complicated. We may use it in the future if it looks useful + + char buffer[2048]; + while (fgets(buffer, sizeof(buffer), stdin)) { + + if (strncmp("Content-length: ", buffer, 16) == 0) { + char* context; + strtok_s(buffer, " ", &context); + int image_size = strtol(strtok_s(NULL, " ", &context), NULL, 10); + + bool success = false; + if (image_size > 0 && actual_image.has_image() == 0) { + if (!actual_image.CreateFromStdin(image_size)) { + fputs("Error, input image can't be decoded.\n", stderr); + return 1; + } + } else if (image_size > 0 && baseline_image.has_image() == 0) { + if (!baseline_image.CreateFromStdin(image_size)) { + fputs("Error, baseline image can't be decoded.\n", stderr); + return 1; + } + } else { + fputs("Error, image size must be specified.\n", stderr); + return 1; + } + } + + if (actual_image.has_image() && baseline_image.has_image()) { + float percent = PercentageDifferent(actual_image, baseline_image); + if (percent > 0.0) { + // failure: The WebKit version also writes the difference image to + // stdout, which seems excessive for our needs. + printf("diff: %01.2f%% failed\n", percent); + } else { + // success + printf("diff: %01.2f%% passed\n", percent); + } + actual_image.Clear(); + baseline_image.Clear(); + } + + fflush(stdout); + } +*/ +} + +int main(int argc, const char* argv[]) { + CommandLine parsed_command_line; + if (parsed_command_line.HasSwitch(kOptionPollStdin)) { + // Watch stdin for filenames. + char stdin_buffer[2048]; + char filename1_buffer[2048]; + bool have_filename1 = false; + while (fgets(stdin_buffer, sizeof(stdin_buffer), stdin)) { + char *newLine = strchr(stdin_buffer, '\n'); + if (newLine) + *newLine = '\0'; + if (!*stdin_buffer) + continue; + + if (have_filename1) { + // CompareImages writes results to stdout unless an error occurred. + if (CompareImages(filename1_buffer, stdin_buffer) == kStatusError) + printf("error\n"); + fflush(stdout); + have_filename1 = false; + } else { + // Save the first filename in another buffer and wait for the second + // filename to arrive via stdin. + strcpy_s(filename1_buffer, sizeof(filename1_buffer), stdin_buffer); + have_filename1 = true; + } + } + return 0; + } + + if (argc == 3) { + return CompareImages(argv[1], argv[2]); + } + + PrintHelp(); + return kStatusError; +} diff --git a/chrome/tools/test/image_diff/image_diff.vcproj b/chrome/tools/test/image_diff/image_diff.vcproj new file mode 100644 index 0000000..77f36ac --- /dev/null +++ b/chrome/tools/test/image_diff/image_diff.vcproj @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="image_diff" + ProjectGUID="{50B079C7-CD01-42D3-B8C4-9F8D9322E822}" + RootNamespace="image_diff" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <Configurations> + <Configuration + Name="Debug|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\debug.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops" + > + <Tool + Name="VCLinkerTool" + SubSystem="1" + /> + <Tool + Name="VCCLCompilerTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + ConfigurationType="1" + InheritedPropertySheets="$(SolutionDir)..\build\common.vsprops;$(SolutionDir)..\build\release.vsprops;$(SolutionDir)..\third_party\libpng\using_libpng.vsprops;$(SolutionDir)..\third_party\zlib\using_zlib.vsprops" + > + <Tool + Name="VCLinkerTool" + SubSystem="1" + /> + <Tool + Name="VCCLCompilerTool" + /> + </Configuration> + </Configurations> + <Files> + <File + RelativePath=".\image_diff.cc" + > + </File> + </Files> +</VisualStudioProject> diff --git a/chrome/tools/test/smoketests.py b/chrome/tools/test/smoketests.py new file mode 100644 index 0000000..0d31ec4 --- /dev/null +++ b/chrome/tools/test/smoketests.py @@ -0,0 +1,263 @@ +#!/bin/env python +# Copyright 2008, Google Inc. +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are +# met: +# +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following disclaimer +# in the documentation and/or other materials provided with the +# distribution. +# * Neither the name of Google Inc. nor the names of its +# contributors may be used to endorse or promote products derived from +# this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +""" +Runs all the available unit tests, layout tests, page-cycler tests, etc. +for a build of Chrome, imitating a buildbot. + +Usage examples: + smoketests.py + smoketests.py --target=debug --build-type=kjs + smoketests.py --nopage-cycler + smoketests.py --tests=unit,ui --verbose + +For a full list of options, pass the '--help' switch. + +[Alternatively, this script will kill all the tests' executables, in case one +got orphaned during a previous run of this script. (This generally only +happens during script development.)] + +""" + +import errno +import optparse +import os +import subprocess +import sys +import time + +import google.httpd_utils +import google.path_utils +import google.process_utils + + +# Keep a global httpd object so it can be killed in the event of errors. +_httpd = None + +# All the available commands, by name. Items in the command-line lists may +# contain various keywords, listed in the "Substitutions" section below. +# The target build directory will be prepended to the first item in each +# command list. +COMMANDS = {'ipc': ['ipc_tests.exe'], + 'unit': ['unit_tests.exe'], + 'ui': ['ui_tests.exe', '%(page_heap)s'], + 'ui-single': ['ui_tests.exe', '--single-process'], + 'test_shell': ['test_shell_tests.exe'], + 'page-cycler-moz': ['page_cycler_tests.exe', + '--gtest_filter=PageCycler*.MozFile'], + 'page-cycler-moz-http': ['page_cycler_tests.exe', + '--gtest_filter=PageCycler*.MozHttp'], + 'page-cycler-intl1': ['page_cycler_tests.exe', + '--gtest_filter=PageCycler*.Intl1File'], + 'page-cycler-intl2': ['page_cycler_tests.exe', + '--gtest_filter=PageCycler*.Intl2File'], + 'page-cycler-bloat-http': ['page_cycler_tests.exe', + '--gtest_filter=PageCycler*.BloatHttp'], + 'startup': ['startup_tests.exe', + '--gtest_filter=Startup*.*'], + 'dest-startup': ['startup_tests.exe', + '--gtest_filter=DestinationsStartupTest.*'], + 'selenium': ['selenium_tests.exe'], + 'plugin': ['plugin_tests.exe'], + 'installer': ['installer_unittests.exe'], + 'webkit': ['%(python)s', + '%(slave_scripts)s/layout_test_wrapper.py', + '--build-type', '%(build_type)s', + '--target', '%(target)s', + '%(page_heap)s'], + } + +# Certain tests are not run for each build type. +SKIPPED = {'Release': ['plugin'], + 'Debug': ['selenium', 'webkit']} + +def _BuildbotScriptPath(sub_dir): + """Returns the full path to the given subdir of tools/buildbot/scripts.""" + this_script_dir = google.path_utils.ScriptDir() + return google.path_utils.FindUpward(this_script_dir, 'tools', 'buildbot', + 'scripts', sub_dir) + + +def _MakeSubstitutions(list, options): + """Makes substitutions in each item of a list and returns the resulting list. + + Args: + list: a list of strings, optionally containing certain %()s substitution + tags listed below + options: options as returned by optparse + """ + this_script_dir = google.path_utils.ScriptDir() + python_path = google.path_utils.FindUpward(this_script_dir, + 'third_party', + 'python_24', + 'python_slave.exe') + + substitutions = {'target': options.target, + 'build_type': options.build_type, + 'page_heap': '', + 'python': python_path, + 'slave_scripts': _BuildbotScriptPath('slave'), + } + if options.build_type == 'kjs': + substitutions['page_heap'] = '--enable-pageheap' + return [word % substitutions for word in list] + + +def main(options, args): + """Runs all the selected tests for the given build type and target.""" + options.build_type = options.build_type.lower() + options.target = options.target.title() + + this_script_dir = google.path_utils.ScriptDir() + test_path = google.path_utils.FindUpward(this_script_dir, + 'chrome', options.target) + + # Add the buildbot script paths to the module search path. + sys.path.insert(0, _BuildbotScriptPath('slave')) + sys.path.insert(0, _BuildbotScriptPath('common')) + + # Collect list of tests to run. + if options.tests == '': + tests = sorted(COMMANDS.keys()) + else: + tests = set() + requested_tests = options.tests.lower().split(',') + for test in requested_tests: + if test in COMMANDS: + tests.add(test) + else: + print 'Ignoring unknown test "%s"' % test + + # Check page-cycler data, since the tests choke if it isn't available. + try: + page_cycler_data = google.path_utils.FindUpward(this_script_dir, + 'data', + 'page_cycler') + except google.path_utils.PathNotFound: + # Were we going to run any page-cycler tests? + if (not options.nopage_cycler and + len([x for x in tests if x.startswith('page-cycler')])): + print 'Skipping page-cycler tests (no data)' + options.nopage_cycler = True + + # Start an httpd if needed. + http_tests = [x for x in tests if x.endswith('-http')] + if http_tests and not options.nopage_cycler and not options.nohttp: + try: + _httpd = google.httpd_utils.StartServer(document_root=page_cycler_data) + except google.httpd_utils.HttpdNotStarted: + print 'Skipping http tests (httpd failed to start)' + options.nohttp = True + + # Remove tests not desired. + if options.nopage_cycler: + tests = [x for x in tests if not x.startswith('page-cycler')] + if options.nowebkit and 'webkit' in tests: + tests.remove('webkit') + if options.nohttp: + tests = [x for x in tests if not x.endswith('-http')] + + # Remove tests skipped for this build target. + for skip in SKIPPED[options.target]: + if skip in tests: + print 'Skipping %s for %s build' % (skip, options.target) + tests.remove(skip) + + if not len(tests): + print 'No tests to run.' + return 0 + + # Run each test, substituting strings as needed. + failures = [] + start_time = time.time() + for test in tests: + test_start_time = time.time() + command = _MakeSubstitutions(COMMANDS[test], options) + command[0] = os.path.join(test_path, command[0]) + if options.verbose: + print + print 'Running %s:' % test, + try: + result = google.process_utils.RunCommand(command, options.verbose) + except google.process_utils.CommandNotFound: + print '%s' % e + if options.verbose: + print test, + print '(%ds)' % (time.time() - test_start_time), + if result: + print 'FAIL' + failures.append(test) + else: + print 'PASS' + + print 'Total time: %ds' % (time.time() - start_time) + if len(failures): + print 'Failed tests:' + print os.linesep.join(failures) + else: + print 'All tests passed. Hurrah!' + + return len(failures) + +if '__main__' == __name__: + option_parser = optparse.OptionParser() + option_parser.add_option('', '--target', default='Release', + help='build target (Debug or Release)') + option_parser.add_option('', '--build-type', default='v8', + help='build type (V8 or KJS), used by webkit tests') + option_parser.add_option('', '--verbose', action='store_true', default=False, + help='show full output from every command') + option_parser.add_option('', '--nopage-cycler', action='store_true', + default=False, help='disable page-cycler tests') + option_parser.add_option('', '--nowebkit', action='store_true', + default=False, help='disable webkit (layout) tests') + option_parser.add_option('', '--nohttp', action='store_true', + default=False, + help="don't run tests (e.g. page_cycler) with http") + option_parser.add_option('', '--tests', default='', + help='comma-separated list of tests to run, from ' + '{%s}' % ', '.join(sorted(COMMANDS.keys()))) + option_parser.add_option('', '--killall', action='store_true', default=False, + help='kill all test executables (and run no tests)') + options, args = option_parser.parse_args() + + if options.killall: + kill_list = _MakeSubstitutions([COMMANDS[x][0] for x in COMMANDS.keys()], + options) + kill_list = set([os.path.basename(x) for x in kill_list]) + sys.exit(google.process_utils.KillAll(kill_list)) + + try: + result = main(options, args) + finally: + # Kill the httpd. + if _httpd: + _httpd.StopServer(force=True) + sys.exit(result) |