summaryrefslogtreecommitdiffstats
path: root/chrome/tools/test
diff options
context:
space:
mode:
authorinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
committerinitial.commit <initial.commit@0039d316-1c4b-4281-b951-d872f2087c98>2008-07-26 23:55:29 +0000
commit09911bf300f1a419907a9412154760efd0b7abc3 (patch)
treef131325fb4e2ad12c6d3504ab75b16dd92facfed /chrome/tools/test
parent586acc5fe142f498261f52c66862fa417c3d52d2 (diff)
downloadchromium_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.pl270
-rw-r--r--chrome/tools/test/image_diff/SConscript106
-rw-r--r--chrome/tools/test/image_diff/image_diff.cc291
-rw-r--r--chrome/tools/test/image_diff/image_diff.vcproj49
-rw-r--r--chrome/tools/test/smoketests.py263
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)