Home | History | Annotate | Download | only in ppapi_test_lib
      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/dev/ppb_testing_dev.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 == PPBTestingDev()->ReadImageData(graphics2d, image, &kOrigin));
    228   bool found_error = false;
    229   for (int y = origin.y; y < origin.y + size.height && !found_error; y++) {
    230     for (int x = origin.x; x < origin.x + size.width && !found_error; x++) {
    231       uint32_t pixel_color = static_cast<uint32_t*>(bitmap)[stride * y + x];
    232       found_error = (pixel_color != expected_color);
    233     }
    234   }
    235 
    236   PPBCore()->ReleaseResource(image);
    237   return !found_error;
    238 }
    239