Index: ppapi/native_client/tests/ppapi_browser/ppb_image_data/ppapi_ppb_image_data.cc |
=================================================================== |
--- ppapi/native_client/tests/ppapi_browser/ppb_image_data/ppapi_ppb_image_data.cc (revision 0) |
+++ ppapi/native_client/tests/ppapi_browser/ppb_image_data/ppapi_ppb_image_data.cc (revision 0) |
@@ -0,0 +1,342 @@ |
+// Copyright (c) 2011 The Native Client Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+// |
+// Test cases for PPB_ImageData functions. |
+// |
+// TODO(polina): use PPB_Testing for additional automatic validation. |
+ |
+#include <string.h> |
+ |
+#include "native_client/src/include/nacl_macros.h" |
+#include "native_client/src/shared/platform/nacl_check.h" |
+#include "native_client/tests/ppapi_test_lib/get_browser_interface.h" |
+#include "native_client/tests/ppapi_test_lib/test_interface.h" |
+#include "ppapi/c/pp_bool.h" |
+#include "ppapi/c/pp_errors.h" |
+#include "ppapi/c/pp_point.h" |
+#include "ppapi/c/pp_rect.h" |
+#include "ppapi/c/pp_size.h" |
+#include "ppapi/c/ppb_core.h" |
+#include "ppapi/c/ppb_graphics_2d.h" |
+#include "ppapi/c/ppb_image_data.h" |
+#include "ppapi/c/ppb_instance.h" |
+#include "ppapi/c/ppb_url_loader.h" |
+ |
+namespace { |
+ |
+const int kPixelSizeInBytes = 4; |
+const PP_Size kOnePixelImageSize = PP_MakeSize(1, 1); |
+const PP_Size kSmallImageSize = PP_MakeSize(30, 30); |
+const PP_Size kLargeImageSize = PP_MakeSize(2048, 2048); |
+const PP_Size kValidImageSize[] = { |
+ kOnePixelImageSize, |
+ kSmallImageSize, |
+ kLargeImageSize |
+}; |
+const int kNumValidImages = sizeof(kValidImageSize) / sizeof(PP_Size); |
+const PP_Size kInvalidImageSize[] = { |
+ PP_MakeSize(100000000, 100000000), |
+ PP_MakeSize(-100000000, 100000000), |
+ PP_MakeSize(-100, 100000000), |
+ PP_MakeSize(100, -100000000), |
+ PP_MakeSize(-100, 100), |
+ PP_MakeSize(-100, -100), |
+ PP_MakeSize(0, 0), |
+ PP_MakeSize(0, 100), |
+ PP_MakeSize(100, 0) |
+}; |
+const int kNumInvalidImages = sizeof(kInvalidImageSize) / sizeof(PP_Size); |
+ |
+union BogusFormat { |
+ int bogus; |
+ PP_ImageDataFormat format; |
+}; |
+ |
+bool IsEqualSize(PP_Size size1, PP_Size size2) { |
+ return (size1.width == size2.width && size1.height == size2.height); |
+} |
+ |
+//////////////////////////////////////////////////////////////////////////////// |
+// Test Cases |
+//////////////////////////////////////////////////////////////////////////////// |
+ |
+// Tests PPB_ImageData::GetNativeImageDataFormat(). |
+void TestGetNativeImageDataFormat() { |
+ bool test_passed = false; |
+ PP_ImageDataFormat format; |
+ // TODO(nfullagar): If new formats are added after this test is written, |
+ // then the switch statement below will need to be updated, and additional |
+ // testing will need to be done in the other test cases below. |
+ // Also, new formats could introduce new pixel sizeis (in bytes), which |
+ // could affect some of the stride checks. |
+ format = PPBImageData()->GetNativeImageDataFormat(); |
+ switch (format) { |
+ case PP_IMAGEDATAFORMAT_BGRA_PREMUL: |
+ case PP_IMAGEDATAFORMAT_RGBA_PREMUL: |
+ test_passed = true; |
+ } |
+ EXPECT(test_passed); |
+ TEST_PASSED; |
+} |
+ |
+// Tests PPB_ImageData::IsImageDataFormatSupported(). |
+void TestIsImageDataFormatSupported() { |
+ PP_ImageDataFormat format; |
+ BogusFormat bogus; |
+ format = PPBImageData()->GetNativeImageDataFormat(); |
+ // EXPECT the format recommended by the browser is supported. |
+ EXPECT(PP_TRUE == PPBImageData()->IsImageDataFormatSupported(format)); |
+ // Invoke with known formats, should not crash. |
+ PPBImageData()->IsImageDataFormatSupported(PP_IMAGEDATAFORMAT_BGRA_PREMUL); |
+ PPBImageData()->IsImageDataFormatSupported(PP_IMAGEDATAFORMAT_RGBA_PREMUL); |
+ // Make up invalid enums and verify they are not supported. |
+ bogus.bogus = -1; |
+ EXPECT(PP_FALSE == PPBImageData()-> |
+ IsImageDataFormatSupported(bogus.format)); |
+ bogus.bogus = 123; |
+ EXPECT(PP_FALSE == PPBImageData()-> |
+ IsImageDataFormatSupported(bogus.format)); |
+ TEST_PASSED; |
+} |
+ |
+// Tests PPB_ImageData::Create(). |
+void TestCreate() { |
+ PP_Resource image_data = kInvalidResource; |
+ BogusFormat bogus; |
+ // Invalid instance and valid size -> expect an invalid resource. |
+ image_data = PPBImageData()->Create(kInvalidInstance, |
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL, &kSmallImageSize, PP_FALSE); |
+ EXPECT(image_data == kInvalidResource); |
+ image_data = PPBImageData()->Create(kInvalidInstance, |
+ PP_IMAGEDATAFORMAT_RGBA_PREMUL, &kSmallImageSize, PP_FALSE); |
+ EXPECT(image_data == kInvalidResource); |
+ image_data = PPBImageData()->Create(kInvalidInstance, |
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL, &kSmallImageSize, PP_TRUE); |
+ EXPECT(image_data == kInvalidResource); |
+ image_data = PPBImageData()->Create(kInvalidInstance, |
+ PP_IMAGEDATAFORMAT_RGBA_PREMUL, &kSmallImageSize, PP_TRUE); |
+ EXPECT(image_data == kInvalidResource); |
+ // NULL size -> Internal error in rpc method, expect an invalid resource. |
+ image_data = PPBImageData()->Create(kInvalidInstance, |
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL, NULL, PP_FALSE); |
+ EXPECT(image_data == kInvalidResource); |
+ image_data = PPBImageData()->Create(kInvalidInstance, |
+ PP_IMAGEDATAFORMAT_RGBA_PREMUL, NULL, PP_FALSE); |
+ EXPECT(image_data == kInvalidResource); |
+ image_data = PPBImageData()->Create(kInvalidInstance, |
+ PP_IMAGEDATAFORMAT_BGRA_PREMUL, NULL, PP_TRUE); |
+ EXPECT(image_data == kInvalidResource); |
+ image_data = PPBImageData()->Create(kInvalidInstance, |
+ PP_IMAGEDATAFORMAT_RGBA_PREMUL, NULL, PP_TRUE); |
+ EXPECT(image_data == kInvalidResource); |
+ // bogus image format -> expect an invalid resource. |
+ bogus.bogus = -1; |
+ image_data = PPBImageData()->Create(pp_instance(), bogus.format, |
+ &kSmallImageSize, PP_FALSE); |
+ EXPECT(image_data == kInvalidResource); |
+ bogus.bogus = 123; |
+ image_data = PPBImageData()->Create(pp_instance(), bogus.format, |
+ &kSmallImageSize, PP_TRUE); |
+ EXPECT(image_data == kInvalidResource); |
+ |
+ PP_Bool kPixelFill[] = {PP_FALSE, PP_TRUE}; |
+ int kNumPixelFill = sizeof(kPixelFill) / sizeof(PP_Bool); |
+ PP_ImageDataFormat native_format = PPBImageData()->GetNativeImageDataFormat(); |
+ for (int j = 0; j < kNumPixelFill; ++j) { |
+ // Valid instance and valid image size should generate a valid resource. |
+ for (int i = 0; i < kNumValidImages; ++i) { |
+ image_data = PPBImageData()->Create(pp_instance(), native_format, |
+ &kValidImageSize[i], kPixelFill[j]); |
+ EXPECT(image_data != kInvalidResource); |
+ PPBCore()->ReleaseResource(image_data); |
+ } |
+ // Valid instance and invalid size should generate an invalid resource. |
+ for (int i = 0; i < kNumInvalidImages; ++i) { |
+ image_data = PPBImageData()->Create(pp_instance(), native_format, |
+ &kInvalidImageSize[i], kPixelFill[j]); |
+ EXPECT(image_data == kInvalidResource); |
+ } |
+ } |
+ TEST_PASSED; |
+} |
+ |
+// Tests PPB_ImageData::IsImageData(). |
+void TestIsImageData() { |
+ // Invalid / non-existent / non-ImageData resource -> false. |
+ EXPECT(PP_FALSE == PPBImageData()->IsImageData(kInvalidResource)); |
+ EXPECT(PP_FALSE == PPBImageData()->IsImageData(kNotAResource)); |
+ PP_Resource url_loader = PPBURLLoader()->Create(pp_instance()); |
+ CHECK(url_loader != kInvalidResource); |
+ EXPECT(PP_FALSE == PPBImageData()->IsImageData(url_loader)); |
+ PPBCore()->ReleaseResource(url_loader); |
+ |
+ PP_ImageDataFormat format = PPBImageData()->GetNativeImageDataFormat(); |
+ |
+ // Created ImageData resource -> true. |
+ PP_Resource image_data = PPBImageData()->Create( |
+ pp_instance(), format, &kSmallImageSize, PP_TRUE); |
+ EXPECT(PP_TRUE == PPBImageData()->IsImageData(image_data)); |
+ |
+ // Released ImageData resource -> false. |
+ PPBCore()->ReleaseResource(image_data); |
+ EXPECT(PP_FALSE == PPBImageData()->IsImageData(image_data)); |
+ TEST_PASSED; |
+} |
+ |
+// Tests PPB_ImageData::Describe(). |
+void TestDescribe() { |
+ PP_Resource image_data = kInvalidResource; |
+ PP_ImageDataFormat format = PPBImageData()->GetNativeImageDataFormat(); |
+ PP_ImageDataDesc description; |
+ |
+ // Valid resource -> output = configuration, true. |
+ image_data = PPBImageData()->Create(pp_instance(), format, &kSmallImageSize, |
+ PP_FALSE); |
+ memset(&description, 0, sizeof(description)); |
+ EXPECT(PP_TRUE == PPBImageData()->Describe(image_data, &description)); |
+ EXPECT(description.format == format); |
+ EXPECT(IsEqualSize(description.size, kSmallImageSize)); |
+ EXPECT(description.stride >= description.size.width * |
+ kPixelSizeInBytes); |
+ PPBCore()->ReleaseResource(image_data); |
+ |
+ image_data = PPBImageData()->Create(pp_instance(), format, &kSmallImageSize, |
+ PP_TRUE); |
+ memset(&description, 0, sizeof(description)); |
+ EXPECT(PP_TRUE == PPBImageData()->Describe(image_data, &description)); |
+ EXPECT(description.format == format); |
+ EXPECT(IsEqualSize(description.size, kSmallImageSize)); |
+ EXPECT(description.stride >= description.size.width * kPixelSizeInBytes); |
+ PPBCore()->ReleaseResource(image_data); |
+ |
+ // NULL outputs -> output = unchanged, false. |
+ EXPECT(PP_FALSE == PPBImageData()->Describe(image_data, NULL)); |
+ |
+ // Invalid / non-existent resource -> output = 0, false. |
+ memset(&description, 0, sizeof(description)); |
+ EXPECT(PP_FALSE == PPBImageData()->Describe(kInvalidResource, &description)); |
+ EXPECT(IsEqualSize(description.size, PP_MakeSize(0, 0))); |
+ EXPECT(PP_FALSE == PPBImageData()->Describe(kNotAResource, &description)); |
+ EXPECT(IsEqualSize(description.size, PP_MakeSize(0, 0))); |
+ TEST_PASSED; |
+} |
+ |
+// Tests PPB_ImageData::Map() & PPB_ImageData::Unmap(). |
+void TestMapUnmap() { |
+ PP_Resource image_data = kInvalidResource; |
+ PP_ImageDataFormat format = PPBImageData()->GetNativeImageDataFormat(); |
+ PP_ImageDataDesc description; |
+ uint8_t *pixel_byte_ptr; |
+ uint8_t *pixel_byte_ptr2; |
+ uint8_t pixel_bytes_or_together; |
+ image_data = PPBImageData()->Create(pp_instance(), format, &kSmallImageSize, |
+ PP_TRUE); |
+ EXPECT(PP_TRUE == PPBImageData()->Describe(image_data, &description)); |
+ int image_size_in_bytes = description.stride * description.size.height; |
+ pixel_byte_ptr = static_cast<uint8_t *>(PPBImageData()->Map(image_data)); |
+ EXPECT(NULL != pixel_byte_ptr); |
+ pixel_bytes_or_together = 0; |
+ // The image was created with a request to zero fill, so verify that |
+ // memory is zero filled. |
+ for (int i = 0; i < image_size_in_bytes; ++i) { |
+ pixel_bytes_or_together = pixel_bytes_or_together | pixel_byte_ptr[i]; |
+ } |
+ EXPECT(0 == pixel_bytes_or_together); |
+ PPBImageData()->Unmap(image_data); |
+ PPBCore()->ReleaseResource(image_data); |
+ // The following shouldn't crash -- it attempts to map an image resource more |
+ // than once, then it attempts to release the resource, then calls unmap with |
+ // the released resource. It then attempts to re-map the resource, which |
+ // should return a NULL pointer. |
+ image_data = PPBImageData()->Create(pp_instance(), format, &kSmallImageSize, |
+ PP_TRUE); |
+ pixel_byte_ptr = static_cast<uint8_t *>(PPBImageData()->Map(image_data)); |
+ EXPECT(NULL != pixel_byte_ptr); |
+ pixel_byte_ptr2 = static_cast<uint8_t *>(PPBImageData()->Map(image_data)); |
+ EXPECT(pixel_byte_ptr == pixel_byte_ptr2); |
+ PPBCore()->ReleaseResource(image_data); |
+ PPBImageData()->Unmap(image_data); |
+ pixel_byte_ptr = static_cast<uint8_t *>(PPBImageData()->Map(image_data)); |
+ EXPECT(NULL == pixel_byte_ptr); |
+ // Attempt to call map/unmap with a few other non-image data resources. |
+ pixel_byte_ptr = static_cast<uint8_t *>(PPBImageData()-> |
+ Map(kInvalidResource)); |
+ EXPECT(NULL == pixel_byte_ptr); |
+ PPBImageData()->Unmap(kInvalidResource); |
+ PP_Resource url_loader = PPBURLLoader()->Create(pp_instance()); |
+ CHECK(url_loader != kInvalidResource); |
+ pixel_byte_ptr = static_cast<uint8_t *>(PPBImageData()->Map(url_loader)); |
+ EXPECT(NULL == pixel_byte_ptr); |
+ PPBCore()->ReleaseResource(url_loader); |
+ TEST_PASSED; |
+} |
+ |
+// Stress testing of a large number of resources. |
+void TestStress() { |
+ // TODO(nfullagar): Increase the number of resources once the cause of the |
+ // stress test flake is fixed. |
+ const int kManyResources = 100; |
+ const int kManyLargeResources = 100; |
+ PP_Resource image_data[kManyResources]; |
+ PP_Resource large_image_data; |
+ PP_ImageDataFormat format = PPBImageData()->GetNativeImageDataFormat(); |
+ |
+ // Create a large number of co-existing memory mapped small images. |
+ for (int i = 0; i < kManyResources; ++i) { |
+ image_data[i] = PPBImageData()->Create(pp_instance(), format, |
+ &kSmallImageSize, PP_TRUE); |
+ EXPECT(image_data[i] != kInvalidResource); |
+ // Check to see if resource id is duplicate. |
+ // TODO(nfullagar): This could be done faster if the test needs to increase |
+ // the number of resources to create. |
+ for (int j = 0; j < i; ++j) { |
+ EXPECT(image_data[j] != image_data[i]); |
+ } |
+ EXPECT(PP_TRUE == PPBImageData()->IsImageData(image_data[i])); |
+ EXPECT(NULL != PPBImageData()->Map(image_data[i])); |
+ } |
+ |
+ // A large number of create-map-unmap-release large images. |
+ // Only one large image exists at a time; make sure memory space isn't |
+ // exhausted. |
+ // TODO(nfullagar): Some platforms (notably 32-bit ones) are unable to |
+ // recycle a large number of large resources. This might be related to: |
+ // http://code.google.com/p/chromium/issues/detail?id=87445 |
+ for (int i = 0; i < kManyLargeResources; i++) { |
+ large_image_data = PPBImageData()->Create(pp_instance(), format, |
+ &kLargeImageSize, PP_TRUE); |
+ EXPECT(large_image_data != kInvalidResource); |
+ EXPECT(PP_TRUE == PPBImageData()->IsImageData(large_image_data)); |
+ EXPECT(NULL != PPBImageData()->Map(large_image_data)); |
+ PPBImageData()->Unmap(large_image_data); |
+ PPBCore()->ReleaseResource(large_image_data); |
+ EXPECT(PP_FALSE == PPBImageData()->IsImageData(large_image_data)); |
+ } |
+ |
+ // Go back and unmap the smaller images. |
+ for (int i = 0; i < kManyResources; i++) { |
+ PPBImageData()->Unmap(image_data[i]); |
+ EXPECT(PP_TRUE == PPBImageData()->IsImageData(image_data[i])); |
+ PPBCore()->ReleaseResource(image_data[i]); |
+ EXPECT(PP_FALSE == PPBImageData()->IsImageData(image_data[i])); |
+ } |
+ |
+ TEST_PASSED; |
+} |
+} // namespace |
+ |
+void SetupTests() { |
+ RegisterTest("TestGetNativeImageDataFormat", TestGetNativeImageDataFormat); |
+ RegisterTest("TestIsImageDataFormatSupported", |
+ TestIsImageDataFormatSupported); |
+ RegisterTest("TestCreate", TestCreate); |
+ RegisterTest("TestIsImageData", TestIsImageData); |
+ RegisterTest("TestDescribe", TestDescribe); |
+ RegisterTest("TestMapUnmap", TestMapUnmap); |
+ RegisterTest("TestStress", TestStress); |
+} |
+ |
+void SetupPluginInterfaces() { |
+ // none |
+} |