diff options
Diffstat (limited to 'webkit/tools/test_shell/image_decoder_unittest.cc')
-rw-r--r-- | webkit/tools/test_shell/image_decoder_unittest.cc | 211 |
1 files changed, 211 insertions, 0 deletions
diff --git a/webkit/tools/test_shell/image_decoder_unittest.cc b/webkit/tools/test_shell/image_decoder_unittest.cc new file mode 100644 index 0000000..9e640fd --- /dev/null +++ b/webkit/tools/test_shell/image_decoder_unittest.cc @@ -0,0 +1,211 @@ +// 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. + +#include "config.h" + +#include <windows.h> + +#include "base/file_util.h" +#include "base/md5.h" +#include "base/path_service.h" +#include "base/scoped_handle.h" +#include "base/scoped_ptr.h" +#include "base/time.h" +#include "webkit/tools/test_shell/image_decoder_unittest.h" + +void ReadFileToVector(const std::wstring& path, Vector<char>* contents) { + std::string contents_str; + file_util::ReadFileToString(path, &contents_str); + contents->resize(contents_str.size()); + memcpy(&contents->first(), contents_str.data(), contents_str.size()); +} + +std::wstring GetMD5SumPath(const std::wstring& path) { + static const std::wstring kDecodedDataExtension(L".md5sum"); + return path + kDecodedDataExtension; +} + +#ifdef CALCULATE_MD5_SUMS +void SaveMD5Sum(const std::wstring& path, WebCore::RGBA32Buffer* buffer) { + // Create the file to write. + ScopedHandle handle(CreateFile(path.c_str(), GENERIC_WRITE, 0, + NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL)); + ASSERT_TRUE(handle.IsValid()); + + // Calculate MD5 sum. + MD5Digest digest; + SkAutoLockPixels bmp_lock(buffer->bitmap()); + MD5Sum(buffer->bitmap().getPixels(), + buffer->rect().width() * buffer->rect().height() * sizeof(unsigned), + &digest); + + // Write sum to disk. + DWORD bytes_written; + ASSERT_TRUE(WriteFile(handle, &digest, sizeof digest, &bytes_written, + NULL)); + ASSERT_EQ(sizeof digest, bytes_written); +} +#else +void VerifyImage(WebCore::ImageDecoder* decoder, + const std::wstring& path, + const std::wstring& md5_sum_path) { + // Make sure decoding can complete successfully. + EXPECT_TRUE(decoder->isSizeAvailable()) << path; + WebCore::RGBA32Buffer* image_buffer = decoder->frameBufferAtIndex(0); + ASSERT_NE(static_cast<WebCore::RGBA32Buffer*>(NULL), image_buffer) << path; + EXPECT_EQ(WebCore::RGBA32Buffer::FrameComplete, image_buffer->status()) << + path; + EXPECT_FALSE(decoder->failed()) << path; + + // Calculate MD5 sum. + MD5Digest actual_digest; + SkAutoLockPixels bmp_lock(image_buffer->bitmap()); + MD5Sum(image_buffer->bitmap().getPixels(), image_buffer->rect().width() * + image_buffer->rect().height() * sizeof(unsigned), &actual_digest); + + // Read the MD5 sum off disk. + std::string file_bytes; + file_util::ReadFileToString(md5_sum_path, &file_bytes); + MD5Digest expected_digest; + ASSERT_EQ(sizeof expected_digest, file_bytes.size()) << path; + memcpy(&expected_digest, file_bytes.data(), sizeof expected_digest); + + // Verify that the sums are the same. + EXPECT_EQ(0, memcmp(&expected_digest, &actual_digest, sizeof(MD5Digest))) << + path; +} +#endif + +void ImageDecoderTest::SetUp() { + ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &data_dir_)); + file_util::AppendToPath(&data_dir_, L"webkit"); + file_util::AppendToPath(&data_dir_, L"data"); + file_util::AppendToPath(&data_dir_, format_ + L"_decoder"); + ASSERT_TRUE(file_util::PathExists(data_dir_)); +} + +std::vector<std::wstring> ImageDecoderTest::GetImageFiles() const { + std::wstring find_string(data_dir_); + file_util::AppendToPath(&find_string, L"*." + format_); + WIN32_FIND_DATA find_data; + ScopedFindFileHandle handle(FindFirstFile(find_string.c_str(), + &find_data)); + EXPECT_TRUE(handle.IsValid()); + + std::vector<std::wstring> image_files; + do { + std::wstring image_path = data_dir_; + file_util::AppendToPath(&image_path, find_data.cFileName); + image_files.push_back(image_path); + } while (FindNextFile(handle, &find_data)); + + return image_files; +} + +bool ImageDecoderTest::ShouldImageFail(const std::wstring& path) const { + static const std::wstring kBadSuffix(L".bad."); + return (path.length() > (kBadSuffix.length() + format_.length()) && + !path.compare(path.length() - format_.length() - kBadSuffix.length(), + kBadSuffix.length(), kBadSuffix)); +} + +void ImageDecoderTest::TestDecoding() const { + const std::vector<std::wstring> image_files(GetImageFiles()); + for (std::vector<std::wstring>::const_iterator i(image_files.begin()); + i != image_files.end(); ++i) { + Vector<char> image_contents; + ReadFileToVector(*i, &image_contents); + + scoped_ptr<WebCore::ImageDecoder> decoder(CreateDecoder()); + RefPtr<WebCore::SharedBuffer> shared_contents(new WebCore::SharedBuffer); + shared_contents->append(image_contents.data(), + static_cast<int>(image_contents.size())); + decoder->setData(shared_contents.get(), true); + + if (ShouldImageFail(*i)) { + // We should always get a non-NULL frame buffer, but when the decoder + // tries to produce it, it should fail, and the frame buffer shouldn't + // complete. + WebCore::RGBA32Buffer* const image_buffer = + decoder->frameBufferAtIndex(0); + ASSERT_NE(static_cast<WebCore::RGBA32Buffer*>(NULL), image_buffer) << + (*i); + EXPECT_NE(image_buffer->status(), WebCore::RGBA32Buffer::FrameComplete) << + (*i); + EXPECT_TRUE(decoder->failed()) << (*i); + continue; + } + +#ifdef CALCULATE_MD5_SUMS + SaveMD5Sum(GetMD5SumPath(*i), decoder->frameBufferAtIndex(0)); +#else + VerifyImage(decoder.get(), *i, GetMD5SumPath(*i)); +#endif + } +} + +#ifndef CALCULATE_MD5_SUMS +void ImageDecoderTest::TestChunkedDecoding() const { + // Init random number generator with current day, so a failing case will fail + // consistently over the course of a whole day. + const Time today = Time::Now().LocalMidnight(); + srand(static_cast<unsigned int>(today.ToInternalValue())); + + const std::vector<std::wstring> image_files(GetImageFiles()); + for (std::vector<std::wstring>::const_iterator i(image_files.begin()); + i != image_files.end(); ++i) { + if (ShouldImageFail(*i)) + continue; + + // Read the file and split it at an arbitrary point. + Vector<char> image_contents; + ReadFileToVector(*i, &image_contents); + const int partial_size = static_cast<int>( + (static_cast<double>(rand()) / RAND_MAX) * image_contents.size()); + RefPtr<WebCore::SharedBuffer> partial_contents(new WebCore::SharedBuffer); + partial_contents->append(image_contents.data(), partial_size); + + // Make sure the image decoder doesn't fail when we ask for the frame buffer + // for this partial image. + scoped_ptr<WebCore::ImageDecoder> decoder(CreateDecoder()); + decoder->setData(partial_contents.get(), false); + EXPECT_NE(static_cast<WebCore::RGBA32Buffer*>(NULL), + decoder->frameBufferAtIndex(0)) << (*i); + EXPECT_FALSE(decoder->failed()) << (*i); + + // Make sure passing the complete image results in successful decoding. + partial_contents->append( + &image_contents.data()[partial_size], + static_cast<int>(image_contents.size() - partial_size)); + decoder->setData(partial_contents.get(), true); + VerifyImage(decoder.get(), *i, GetMD5SumPath(*i)); + } +} +#endif |