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/tests/test_var.h" 6 7#include <string.h> 8 9#include <limits> 10 11#include "ppapi/c/dev/ppb_testing_dev.h" 12#include "ppapi/c/pp_var.h" 13#include "ppapi/c/ppb_var.h" 14#include "ppapi/cpp/instance.h" 15#include "ppapi/cpp/module.h" 16#include "ppapi/cpp/var.h" 17#include "ppapi/tests/testing_instance.h" 18 19namespace { 20 21uint32_t kInvalidLength = static_cast<uint32_t>(-1); 22 23} // namespace 24 25REGISTER_TEST_CASE(Var); 26 27bool TestVar::Init() { 28 var_interface_ = static_cast<const PPB_Var*>( 29 pp::Module::Get()->GetBrowserInterface(PPB_VAR_INTERFACE)); 30 return var_interface_ && CheckTestingInterface(); 31} 32 33void TestVar::RunTests(const std::string& filter) { 34 RUN_TEST(BasicString, filter); 35 RUN_TEST(InvalidAndEmpty, filter); 36 RUN_TEST(InvalidUtf8, filter); 37 RUN_TEST(NullInputInUtf8Conversion, filter); 38 RUN_TEST(ValidUtf8, filter); 39 RUN_TEST(Utf8WithEmbeddedNulls, filter); 40 RUN_TEST(VarToUtf8ForWrongType, filter); 41} 42 43std::string TestVar::TestBasicString() { 44 uint32_t before_object = testing_interface_->GetLiveObjectsForInstance( 45 instance_->pp_instance()); 46 { 47 const char kStr[] = "Hello"; 48 const uint32_t kStrLen(sizeof(kStr) - 1); 49 PP_Var str = var_interface_->VarFromUtf8(kStr, kStrLen); 50 ASSERT_EQ(PP_VARTYPE_STRING, str.type); 51 52 // Reading back the string should work. 53 uint32_t len = 0; 54 const char* result = var_interface_->VarToUtf8(str, &len); 55 ASSERT_EQ(kStrLen, len); 56 ASSERT_EQ(0, strncmp(kStr, result, kStrLen)); 57 58 // Destroy the string, readback should now fail. 59 var_interface_->Release(str); 60 result = var_interface_->VarToUtf8(str, &len); 61 ASSERT_EQ(0, len); 62 ASSERT_EQ(NULL, result); 63 } 64 65 // Make sure we can assign a C++ object to itself and it stays alive. 66 { 67 pp::Var a("test"); 68 a = a; 69 ASSERT_TRUE(a.AsString() == "test"); 70 } 71 72 // Make sure nothing leaked. 73 ASSERT_TRUE(testing_interface_->GetLiveObjectsForInstance( 74 instance_->pp_instance()) == before_object); 75 76 PASS(); 77} 78 79std::string TestVar::TestInvalidAndEmpty() { 80 PP_Var invalid_string; 81 invalid_string.type = PP_VARTYPE_STRING; 82 invalid_string.value.as_id = 31415926; 83 84 // Invalid strings should give NULL as the return value. 85 uint32_t len = std::numeric_limits<uint32_t>::max(); 86 const char* result = var_interface_->VarToUtf8(invalid_string, &len); 87 ASSERT_EQ(0, len); 88 ASSERT_EQ(NULL, result); 89 90 // Same with vars that are not strings. 91 len = std::numeric_limits<uint32_t>::max(); 92 pp::Var int_var(42); 93 result = var_interface_->VarToUtf8(int_var.pp_var(), &len); 94 ASSERT_EQ(0, len); 95 ASSERT_EQ(NULL, result); 96 97 // Empty strings should return non-NULL. 98 pp::Var empty_string(""); 99 len = std::numeric_limits<uint32_t>::max(); 100 result = var_interface_->VarToUtf8(empty_string.pp_var(), &len); 101 ASSERT_EQ(0, len); 102 ASSERT_NE(NULL, result); 103 104 PASS(); 105} 106 107std::string TestVar::TestInvalidUtf8() { 108 // utf8じゃない (japanese for "is not utf8") in shift-jis encoding. 109 static const char kSjisString[] = "utf8\x82\xb6\x82\xe1\x82\xc8\x82\xa2"; 110 pp::Var sjis(kSjisString); 111 if (!sjis.is_null()) 112 return "Non-UTF8 string was permitted erroneously."; 113 114 PASS(); 115} 116 117std::string TestVar::TestNullInputInUtf8Conversion() { 118 // This test talks directly to the C interface to access edge cases that 119 // cannot be exercised via the C++ interface. 120 PP_Var converted_string; 121 122 // 0-length string should not dereference input string, and should produce 123 // an empty string. 124 converted_string = var_interface_->VarFromUtf8(NULL, 0); 125 if (converted_string.type != PP_VARTYPE_STRING) { 126 return "Expected 0 length to return empty string."; 127 } 128 129 // Now convert it back. 130 uint32_t length = kInvalidLength; 131 const char* result = NULL; 132 result = var_interface_->VarToUtf8(converted_string, &length); 133 if (length != 0) { 134 return "Expected 0 length string on conversion."; 135 } 136 if (result == NULL) { 137 return "Expected a non-null result for 0-lengthed string from VarToUtf8."; 138 } 139 var_interface_->Release(converted_string); 140 141 // Should not crash, and make an empty string. 142 const char* null_string = NULL; 143 pp::Var null_var(null_string); 144 if (!null_var.is_string() || null_var.AsString() != "") { 145 return "Expected NULL input to make an empty string Var."; 146 } 147 148 PASS(); 149} 150 151std::string TestVar::TestValidUtf8() { 152 // From UTF8 string -> PP_Var. 153 // Chinese for "I am utf8." 154 static const char kValidUtf8[] = "\xe6\x88\x91\xe6\x98\xafutf8."; 155 pp::Var converted_string(kValidUtf8); 156 157 if (converted_string.is_null()) 158 return "Unable to convert valid utf8 to var."; 159 160 // Since we're already here, test PP_Var back to UTF8 string. 161 std::string returned_string = converted_string.AsString(); 162 163 // We need to check against 1 less than sizeof because the resulting string 164 // is technically not NULL terminated by API design. 165 if (returned_string.size() != sizeof(kValidUtf8) - 1) { 166 return "Unable to convert utf8 string back from var."; 167 } 168 if (returned_string != kValidUtf8) { 169 return "String mismatches on conversion back from PP_Var."; 170 } 171 172 PASS(); 173} 174 175std::string TestVar::TestUtf8WithEmbeddedNulls() { 176 // From UTF8 string with embedded nulls -> PP_Var. 177 // Chinese for "also utf8." 178 static const char kUtf8WithEmbededNull[] = "\xe6\xb9\x9f\xe6\x98\xaf\0utf8."; 179 std::string orig_string(kUtf8WithEmbededNull, 180 sizeof(kUtf8WithEmbededNull) -1); 181 pp::Var converted_string(orig_string); 182 183 if (converted_string.is_null()) 184 return "Unable to convert utf8 with embedded nulls to var."; 185 186 // Since we're already here, test PP_Var back to UTF8 string. 187 std::string returned_string = converted_string.AsString(); 188 189 if (returned_string.size() != orig_string.size()) { 190 return "Unable to convert utf8 with embedded nulls back from var."; 191 } 192 if (returned_string != orig_string) { 193 return "String mismatches on conversion back from PP_Var."; 194 } 195 196 PASS(); 197} 198 199std::string TestVar::TestVarToUtf8ForWrongType() { 200 uint32_t length = kInvalidLength; 201 const char* result = NULL; 202 result = var_interface_->VarToUtf8(PP_MakeUndefined(), &length); 203 if (length != 0) { 204 return "Expected 0 on string conversion from Void var."; 205 } 206 if (result != NULL) { 207 return "Expected NULL on string conversion from Void var."; 208 } 209 210 length = kInvalidLength; 211 result = NULL; 212 result = var_interface_->VarToUtf8(PP_MakeNull(), &length); 213 if (length != 0) { 214 return "Expected 0 on string conversion from Null var."; 215 } 216 if (result != NULL) { 217 return "Expected NULL on string conversion from Null var."; 218 } 219 220 length = kInvalidLength; 221 result = NULL; 222 result = var_interface_->VarToUtf8(PP_MakeBool(PP_TRUE), &length); 223 if (length != 0) { 224 return "Expected 0 on string conversion from Bool var."; 225 } 226 if (result != NULL) { 227 return "Expected NULL on string conversion from Bool var."; 228 } 229 230 length = kInvalidLength; 231 result = NULL; 232 result = var_interface_->VarToUtf8(PP_MakeInt32(1), &length); 233 if (length != 0) { 234 return "Expected 0 on string conversion from Int32 var."; 235 } 236 if (result != NULL) { 237 return "Expected NULL on string conversion from Int32 var."; 238 } 239 240 length = kInvalidLength; 241 result = NULL; 242 result = var_interface_->VarToUtf8(PP_MakeDouble(1.0), &length); 243 if (length != 0) { 244 return "Expected 0 on string conversion from Double var."; 245 } 246 if (result != NULL) { 247 return "Expected NULL on string conversion from Double var."; 248 } 249 250 PASS(); 251} 252 253