1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "ppapi/native_client/tests/ppapi_test_lib/test_interface.h" 6 7 #include <string.h> 8 #include <map> 9 #include <new> 10 11 #include "native_client/src/include/nacl_macros.h" 12 #include "native_client/src/shared/platform/nacl_check.h" 13 14 #include "ppapi/c/pp_instance.h" 15 #include "ppapi/c/pp_module.h" 16 #include "ppapi/c/pp_size.h" 17 #include "ppapi/c/pp_rect.h" 18 #include "ppapi/c/pp_var.h" 19 #include "ppapi/c/ppb_core.h" 20 #include "ppapi/c/ppb_graphics_2d.h" 21 #include "ppapi/c/ppb_image_data.h" 22 #include "ppapi/c/ppb_instance.h" 23 #include "ppapi/c/ppb_messaging.h" 24 #include "ppapi/c/ppb_var.h" 25 #include "ppapi/c/private/ppb_testing_private.h" 26 27 #include "ppapi/native_client/tests/ppapi_test_lib/get_browser_interface.h" 28 #include "ppapi/native_client/tests/ppapi_test_lib/internal_utils.h" 29 30 void PostTestMessage(nacl::string test_name, nacl::string message) { 31 nacl::string test_message = test_name; 32 test_message += ":"; 33 test_message += message; 34 PP_Var post_var = PPBVar()->VarFromUtf8(test_message.c_str(), 35 test_message.size()); 36 PPBMessaging()->PostMessage(pp_instance(), post_var); 37 PPBVar()->Release(post_var); 38 } 39 40 PP_Var PP_MakeString(const char* s) { 41 return PPBVar()->VarFromUtf8(s, strlen(s)); 42 } 43 44 nacl::string StringifyVar(const PP_Var& var) { 45 uint32_t dummy_size; 46 switch (var.type) { 47 default: 48 return "<UNKNOWN>" + toString(var.type); 49 case PP_VARTYPE_NULL: 50 return "<NULL>"; 51 case PP_VARTYPE_BOOL: 52 return "<BOOL>" + toString(var.value.as_bool); 53 case PP_VARTYPE_INT32: 54 return "<INT32>" + toString(var.value.as_int); 55 case PP_VARTYPE_DOUBLE: 56 return "<DOUBLE>" + toString(var.value.as_double); 57 case PP_VARTYPE_STRING: 58 return "<STRING>" + nacl::string(PPBVar()->VarToUtf8(var, &dummy_size)); 59 } 60 } 61 62 //////////////////////////////////////////////////////////////////////////////// 63 // Test registration 64 //////////////////////////////////////////////////////////////////////////////// 65 66 namespace { 67 68 class TestTable { 69 public: 70 // Return singleton intsance. 71 static TestTable* Get() { 72 static TestTable table; 73 return &table; 74 } 75 76 void AddTest(nacl::string test_name, TestFunction test_function) { 77 test_map_[test_name] = test_function; 78 } 79 void RunTest(nacl::string test_name); 80 81 private: 82 NACL_DISALLOW_COPY_AND_ASSIGN(TestTable); 83 84 TestTable() {} 85 86 typedef std::map<nacl::string, TestFunction> TestMap; 87 TestMap test_map_; 88 }; 89 90 void TestTable::RunTest(nacl::string test_name) { 91 TestMap::iterator it = test_map_.find(test_name); 92 if (it == test_map_.end()) { 93 PostTestMessage(test_name, "NOTFOUND"); 94 return; 95 } 96 CHECK(it->second != NULL); 97 TestFunction test_function = it->second; 98 return test_function(); 99 } 100 101 } // namespace 102 103 void RegisterTest(nacl::string test_name, TestFunction test_func) { 104 TestTable::Get()->AddTest(test_name, test_func); 105 } 106 107 void RunTest(nacl::string test_name) { 108 TestTable::Get()->RunTest(test_name); 109 } 110 111 //////////////////////////////////////////////////////////////////////////////// 112 // Testable callback support 113 //////////////////////////////////////////////////////////////////////////////// 114 115 namespace { 116 117 struct CallbackInfo { 118 nacl::string callback_name; 119 PP_CompletionCallback user_callback; 120 }; 121 122 void ReportCallbackInvocationToJS(const char* callback_name) { 123 PP_Var callback_var = PPBVar()->VarFromUtf8(callback_name, 124 strlen(callback_name)); 125 // Report using postmessage for async tests. 126 PPBMessaging()->PostMessage(pp_instance(), callback_var); 127 PPBVar()->Release(callback_var); 128 } 129 130 void CallbackWrapper(void* user_data, int32_t result) { 131 CallbackInfo* callback_info = reinterpret_cast<CallbackInfo*>(user_data); 132 PP_RunCompletionCallback(&callback_info->user_callback, result); 133 ReportCallbackInvocationToJS(callback_info->callback_name.c_str()); 134 delete callback_info; 135 } 136 137 } // namespace 138 139 PP_CompletionCallback MakeTestableCompletionCallback( 140 const char* callback_name, // Tested for by JS harness. 141 PP_CompletionCallback_Func func, 142 void* user_data) { 143 CHECK(callback_name != NULL && strlen(callback_name) > 0); 144 CHECK(func != NULL); 145 146 CallbackInfo* callback_info = new(std::nothrow) CallbackInfo; 147 CHECK(callback_info != NULL); 148 callback_info->callback_name = callback_name; 149 callback_info->user_callback = 150 PP_MakeOptionalCompletionCallback(func, user_data); 151 152 return PP_MakeOptionalCompletionCallback(CallbackWrapper, callback_info); 153 } 154 155 PP_CompletionCallback MakeTestableCompletionCallback( 156 const char* callback_name, // Tested for by JS harness. 157 PP_CompletionCallback_Func func) { 158 return MakeTestableCompletionCallback(callback_name, func, NULL); 159 } 160 161 162 //////////////////////////////////////////////////////////////////////////////// 163 // PPAPI Helpers 164 //////////////////////////////////////////////////////////////////////////////// 165 166 bool IsSizeInRange(PP_Size size, PP_Size min_size, PP_Size max_size) { 167 return (min_size.width <= size.width && size.width <= max_size.width && 168 min_size.height <= size.height && size.height <= max_size.height); 169 } 170 171 bool IsSizeEqual(PP_Size size, PP_Size expected) { 172 return (size.width == expected.width && size.height == expected.height); 173 } 174 175 bool IsRectEqual(PP_Rect position, PP_Rect expected) { 176 return (position.point.x == expected.point.x && 177 position.point.y == expected.point.y && 178 IsSizeEqual(position.size, expected.size)); 179 } 180 181 uint32_t FormatColor(PP_ImageDataFormat format, ColorPremul color) { 182 if (format == PP_IMAGEDATAFORMAT_BGRA_PREMUL) 183 return (color.A << 24) | (color.R << 16) | (color.G << 8) | (color.B); 184 else if (format == PP_IMAGEDATAFORMAT_RGBA_PREMUL) 185 return (color.A << 24) | (color.B << 16) | (color.G << 8) | (color.R); 186 else 187 NACL_NOTREACHED(); 188 } 189 190 PP_Resource CreateImageData(PP_Size size, ColorPremul pixel_color, void** bmp) { 191 PP_ImageDataFormat image_format = PPBImageData()->GetNativeImageDataFormat(); 192 uint32_t formatted_pixel_color = FormatColor(image_format, pixel_color); 193 PP_Resource image_data = PPBImageData()->Create( 194 pp_instance(), image_format, &size, PP_TRUE /*init_to_zero*/); 195 CHECK(image_data != kInvalidResource); 196 PP_ImageDataDesc image_desc; 197 CHECK(PPBImageData()->Describe(image_data, &image_desc) == PP_TRUE); 198 *bmp = NULL; 199 *bmp = PPBImageData()->Map(image_data); 200 CHECK(*bmp != NULL); 201 uint32_t* bmp_words = static_cast<uint32_t*>(*bmp); 202 int num_pixels = image_desc.stride / kBytesPerPixel * image_desc.size.height; 203 for (int i = 0; i < num_pixels; i++) 204 bmp_words[i] = formatted_pixel_color; 205 return image_data; 206 } 207 208 bool IsImageRectOnScreen(PP_Resource graphics2d, 209 PP_Point origin, 210 PP_Size size, 211 ColorPremul color) { 212 PP_Size size2d; 213 PP_Bool dummy; 214 CHECK(PP_TRUE == PPBGraphics2D()->Describe(graphics2d, &size2d, &dummy)); 215 216 void* bitmap = NULL; 217 PP_Resource image = CreateImageData(size2d, kOpaqueBlack, &bitmap); 218 219 PP_ImageDataDesc image_desc; 220 CHECK(PP_TRUE == PPBImageData()->Describe(image, &image_desc)); 221 int32_t stride = image_desc.stride / kBytesPerPixel; // width + padding. 222 uint32_t expected_color = FormatColor(image_desc.format, color); 223 CHECK(origin.x >= 0 && origin.y >= 0 && 224 (origin.x + size.width) <= stride && 225 (origin.y + size.height) <= image_desc.size.height); 226 227 CHECK(PP_TRUE == PPBTestingPrivate()->ReadImageData( 228 graphics2d, image, &kOrigin)); 229 bool found_error = false; 230 for (int y = origin.y; y < origin.y + size.height && !found_error; y++) { 231 for (int x = origin.x; x < origin.x + size.width && !found_error; x++) { 232 uint32_t pixel_color = static_cast<uint32_t*>(bitmap)[stride * y + x]; 233 found_error = (pixel_color != expected_color); 234 } 235 } 236 237 PPBCore()->ReleaseResource(image); 238 return !found_error; 239 } 240