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