| OLD | NEW |
| (Empty) |
| 1 // Copyright 2009 Google Inc. | |
| 2 // | |
| 3 // Licensed under the Apache License, Version 2.0 (the "License"); | |
| 4 // you may not use this file except in compliance with the License. | |
| 5 // You may obtain a copy of the License at | |
| 6 // | |
| 7 // http://www.apache.org/licenses/LICENSE-2.0 | |
| 8 // | |
| 9 // Unless required by applicable law or agreed to in writing, software | |
| 10 // distributed under the License is distributed on an "AS IS" BASIS, | |
| 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 12 // See the License for the specific language governing permissions and | |
| 13 // limitations under the License. | |
| 14 // ======================================================================== | |
| 15 | |
| 16 #include "omaha/plugins/update/npapi/variant_utils.h" | |
| 17 #include <atlbase.h> | |
| 18 #include <string.h> | |
| 19 #include <stdlib.h> | |
| 20 #include "omaha/plugins/update/npapi/testing/dispatch_host_test_interface.h" | |
| 21 #include "omaha/plugins/update/npapi/testing/stubs.h" | |
| 22 #include "omaha/testing/unit_test.h" | |
| 23 | |
| 24 namespace omaha { | |
| 25 | |
| 26 class VariantUtilsTest : public testing::Test { | |
| 27 protected: | |
| 28 virtual void SetUp() { | |
| 29 VOID_TO_NPVARIANT(np_variant_); | |
| 30 } | |
| 31 | |
| 32 virtual void TearDown() { | |
| 33 NPN_ReleaseVariantValue(&np_variant_); | |
| 34 } | |
| 35 | |
| 36 void TestNPV2V() { | |
| 37 NPVariantToVariant(NULL, np_variant_, &variant_); | |
| 38 ExpectTypesEquivalent(); | |
| 39 } | |
| 40 | |
| 41 void TestV2NPV() { | |
| 42 NPN_ReleaseVariantValue(&np_variant_); | |
| 43 VariantToNPVariant(NULL, variant_, &np_variant_); | |
| 44 ExpectTypesEquivalent(); | |
| 45 } | |
| 46 | |
| 47 void ExpectTypesEquivalent() { | |
| 48 switch (V_VT(&variant_)) { | |
| 49 case VT_EMPTY: | |
| 50 EXPECT_TRUE(NPVARIANT_IS_VOID(np_variant_)); | |
| 51 return; | |
| 52 break; | |
| 53 case VT_NULL: | |
| 54 EXPECT_TRUE(NPVARIANT_IS_NULL(np_variant_)); | |
| 55 return; | |
| 56 break; | |
| 57 case VT_BOOL: | |
| 58 EXPECT_TRUE(NPVARIANT_IS_BOOLEAN(np_variant_)); | |
| 59 return; | |
| 60 break; | |
| 61 case VT_I4: | |
| 62 case VT_UI4: | |
| 63 EXPECT_TRUE(NPVARIANT_IS_INT32(np_variant_)); | |
| 64 return; | |
| 65 break; | |
| 66 case VT_R8: | |
| 67 EXPECT_TRUE(NPVARIANT_IS_DOUBLE(np_variant_)); | |
| 68 return; | |
| 69 break; | |
| 70 case VT_BSTR: | |
| 71 EXPECT_TRUE(NPVARIANT_IS_STRING(np_variant_)); | |
| 72 return; | |
| 73 break; | |
| 74 case VT_DISPATCH: | |
| 75 EXPECT_TRUE(NPVARIANT_IS_OBJECT(np_variant_)); | |
| 76 return; | |
| 77 break; | |
| 78 default: | |
| 79 break; | |
| 80 } | |
| 81 ASSERT(false, (L"Expected equivalent types but got the following instead:\n" | |
| 82 L" np_variant_.type -> %d\n V_VT(&variant_) -> %d\n", | |
| 83 np_variant_.type, V_VT(&variant_))); | |
| 84 } | |
| 85 | |
| 86 NPVariant np_variant_; | |
| 87 CComVariant variant_; | |
| 88 }; | |
| 89 | |
| 90 TEST_F(VariantUtilsTest, NPVariantToVariant_Void) { | |
| 91 VOID_TO_NPVARIANT(np_variant_); | |
| 92 TestNPV2V(); | |
| 93 } | |
| 94 | |
| 95 TEST_F(VariantUtilsTest, NPVariantToVariant_Null) { | |
| 96 NULL_TO_NPVARIANT(np_variant_); | |
| 97 TestNPV2V(); | |
| 98 } | |
| 99 | |
| 100 TEST_F(VariantUtilsTest, NPVariantToVariant_Bool) { | |
| 101 BOOLEAN_TO_NPVARIANT(true, np_variant_); | |
| 102 TestNPV2V(); | |
| 103 EXPECT_EQ(VARIANT_TRUE, V_BOOL(&variant_)); | |
| 104 | |
| 105 BOOLEAN_TO_NPVARIANT(false, np_variant_); | |
| 106 TestNPV2V(); | |
| 107 EXPECT_EQ(VARIANT_FALSE, V_BOOL(&variant_)); | |
| 108 } | |
| 109 | |
| 110 TEST_F(VariantUtilsTest, NPVariantToVariant_Int32) { | |
| 111 INT32_TO_NPVARIANT(kint32min, np_variant_); | |
| 112 TestNPV2V(); | |
| 113 EXPECT_EQ(kint32min, V_I4(&variant_)); | |
| 114 | |
| 115 INT32_TO_NPVARIANT(0, np_variant_); | |
| 116 TestNPV2V(); | |
| 117 EXPECT_EQ(0, V_I4(&variant_)); | |
| 118 | |
| 119 INT32_TO_NPVARIANT(kint32max, np_variant_); | |
| 120 TestNPV2V(); | |
| 121 EXPECT_EQ(kint32max, V_I4(&variant_)); | |
| 122 } | |
| 123 | |
| 124 TEST_F(VariantUtilsTest, NPVariantToVariant_Double) { | |
| 125 DOUBLE_TO_NPVARIANT(-1, np_variant_); | |
| 126 TestNPV2V(); | |
| 127 EXPECT_DOUBLE_EQ(-1, V_R8(&variant_)); | |
| 128 | |
| 129 DOUBLE_TO_NPVARIANT(0, np_variant_); | |
| 130 TestNPV2V(); | |
| 131 EXPECT_DOUBLE_EQ(0, V_R8(&variant_)); | |
| 132 | |
| 133 DOUBLE_TO_NPVARIANT(static_cast<double>(kuint64max), | |
| 134 np_variant_); | |
| 135 TestNPV2V(); | |
| 136 EXPECT_DOUBLE_EQ(static_cast<double>(kuint64max), V_R8(&variant_)); | |
| 137 } | |
| 138 | |
| 139 TEST_F(VariantUtilsTest, NPVariantToVariant_String) { | |
| 140 // TODO(omaha): _strdup depends on an implementation detail of the stubs. | |
| 141 STRINGZ_TO_NPVARIANT(_strdup(""), np_variant_); | |
| 142 TestNPV2V(); | |
| 143 EXPECT_STREQ(L"", V_BSTR(&variant_)); | |
| 144 | |
| 145 // Force the length to be zero. | |
| 146 STRINGZ_TO_NPVARIANT(_strdup("junk"), np_variant_); | |
| 147 np_variant_.value.stringValue.UTF8Length = 0; | |
| 148 TestNPV2V(); | |
| 149 EXPECT_STREQ(L"", V_BSTR(&variant_)); | |
| 150 | |
| 151 STRINGZ_TO_NPVARIANT(_strdup("ROBERT'); DROP TABLE Students; --"), | |
| 152 np_variant_); | |
| 153 TestNPV2V(); | |
| 154 EXPECT_STREQ(L"ROBERT'); DROP TABLE Students; --", V_BSTR(&variant_)); | |
| 155 | |
| 156 // Check that NPVariantToVariant properly converts UTF-8 to UTF-16. | |
| 157 STRINGZ_TO_NPVARIANT(_strdup("one: \xe4\xb8\x80"), np_variant_); | |
| 158 TestNPV2V(); | |
| 159 EXPECT_STREQ(L"one: \x4e00", V_BSTR(&variant_)); | |
| 160 } | |
| 161 /* | |
| 162 TEST_F(VariantUtilsTest, NPVariantToVariant_Unsupported) { | |
| 163 // NPVariantType_Object -> VT_DISPATCH conversion is not supported. | |
| 164 ExpectAsserts expect_asserts; | |
| 165 OBJECT_TO_NPVARIANT(NULL, np_variant_); | |
| 166 variant_ = 24; | |
| 167 NPVariantToVariant(NULL, np_variant_, &variant_); | |
| 168 EXPECT_EQ(VT_EMPTY, V_VT(&variant_)); | |
| 169 // Manual cleanup, since OBJECT_TO_NPVARIANT macro was used with a NULL | |
| 170 // NPObject, which is normally illegal. | |
| 171 VOID_TO_NPVARIANT(np_variant_); | |
| 172 } | |
| 173 */ | |
| 174 TEST_F(VariantUtilsTest, VariantToNPVariant_VT_EMPTY) { | |
| 175 variant_.ChangeType(VT_EMPTY); | |
| 176 TestV2NPV(); | |
| 177 } | |
| 178 | |
| 179 TEST_F(VariantUtilsTest, VariantToNPVariant_VT_NULL) { | |
| 180 variant_.ChangeType(VT_NULL); | |
| 181 TestV2NPV(); | |
| 182 } | |
| 183 | |
| 184 TEST_F(VariantUtilsTest, VariantToNPVariant_VT_BOOL) { | |
| 185 variant_ = true; | |
| 186 TestV2NPV(); | |
| 187 EXPECT_TRUE(np_variant_.value.boolValue); | |
| 188 | |
| 189 variant_ = false; | |
| 190 TestV2NPV(); | |
| 191 EXPECT_FALSE(np_variant_.value.boolValue); | |
| 192 } | |
| 193 | |
| 194 TEST_F(VariantUtilsTest, VariantToNPVariant_VT_I4) { | |
| 195 variant_ = kint32max; | |
| 196 TestV2NPV(); | |
| 197 EXPECT_EQ(kint32max, np_variant_.value.intValue); | |
| 198 | |
| 199 variant_ = 0; | |
| 200 TestV2NPV(); | |
| 201 EXPECT_EQ(0, np_variant_.value.intValue); | |
| 202 | |
| 203 variant_ = kint32min; | |
| 204 TestV2NPV(); | |
| 205 EXPECT_EQ(kint32min, np_variant_.value.intValue); | |
| 206 } | |
| 207 | |
| 208 TEST_F(VariantUtilsTest, VariantToNPVariant_VT_UI4) { | |
| 209 variant_ = 0U; | |
| 210 TestV2NPV(); | |
| 211 EXPECT_EQ(0, np_variant_.value.intValue); | |
| 212 | |
| 213 variant_ = static_cast<uint32>(kint32max); | |
| 214 TestV2NPV(); | |
| 215 EXPECT_EQ(kint32max, np_variant_.value.intValue); | |
| 216 | |
| 217 // MSIE can natively support VT_UI4. Unfortunately, Firefox cannot. | |
| 218 // Check that kuint32max wraps around to -1. | |
| 219 variant_ = kuint32max; | |
| 220 TestV2NPV(); | |
| 221 EXPECT_EQ(-1, np_variant_.value.intValue); | |
| 222 } | |
| 223 | |
| 224 TEST_F(VariantUtilsTest, VariantToNPVariant_VT_R8) { | |
| 225 variant_ = 0.0; | |
| 226 TestV2NPV(); | |
| 227 EXPECT_DOUBLE_EQ(0.0, np_variant_.value.doubleValue); | |
| 228 | |
| 229 variant_ = -1.0; | |
| 230 TestV2NPV(); | |
| 231 EXPECT_DOUBLE_EQ(-1.0, np_variant_.value.doubleValue); | |
| 232 | |
| 233 variant_ = static_cast<double>(kuint64max); | |
| 234 TestV2NPV(); | |
| 235 EXPECT_DOUBLE_EQ(static_cast<double>(kuint64max), | |
| 236 np_variant_.value.doubleValue); | |
| 237 } | |
| 238 | |
| 239 TEST_F(VariantUtilsTest, VariantToNPVariant_VT_BSTR) { | |
| 240 variant_ = ""; | |
| 241 TestV2NPV(); | |
| 242 EXPECT_STREQ("", np_variant_.value.stringValue.UTF8Characters); | |
| 243 | |
| 244 variant_ = L"sudo make me a sandwich"; | |
| 245 TestV2NPV(); | |
| 246 EXPECT_STREQ("sudo make me a sandwich", | |
| 247 np_variant_.value.stringValue.UTF8Characters); | |
| 248 | |
| 249 // A NULL BSTR should be treated as an empty string. | |
| 250 V_VT(&variant_) = VT_BSTR; | |
| 251 V_BSTR(&variant_) = NULL; | |
| 252 TestV2NPV(); | |
| 253 EXPECT_STREQ("", np_variant_.value.stringValue.UTF8Characters); | |
| 254 | |
| 255 // Check that VariantToNPVariant properly converts UTF-16 to UTF-8. | |
| 256 variant_ = L"one: \x4e00"; | |
| 257 TestV2NPV(); | |
| 258 EXPECT_STREQ("one: \xe4\xb8\x80", | |
| 259 np_variant_.value.stringValue.UTF8Characters); | |
| 260 } | |
| 261 | |
| 262 TEST_F(VariantUtilsTest, VariantToNPVariant_VT_DISPATCH) { | |
| 263 CComPtr<IDispatch> dispatch; | |
| 264 ASSERT_SUCCEEDED( | |
| 265 CComCoClass<DispatchHostTestInterface>::CreateInstance(&dispatch)); | |
| 266 variant_ = dispatch; | |
| 267 TestV2NPV(); | |
| 268 | |
| 269 // Check that the wrapped object's methods can be called. | |
| 270 NPIdentifierFactory identifier; | |
| 271 NPVariant result; | |
| 272 VOID_TO_NPVARIANT(result); | |
| 273 EXPECT_TRUE(NPN_Invoke(NULL, np_variant_.value.objectValue, | |
| 274 identifier.Create("Random"), NULL, 0, &result)); | |
| 275 EXPECT_TRUE(NPVARIANT_IS_INT32(result)); | |
| 276 EXPECT_EQ(42, result.value.intValue); | |
| 277 } | |
| 278 | |
| 279 TEST_F(VariantUtilsTest, VariantToNPVariant_Unsupported) { | |
| 280 // Legal variant types inferred from oaidl.idl and wtypes.h. Note that some | |
| 281 // types that aren't marked as appearing in VARIANTs still have a VARIANT | |
| 282 // field for that type, so they are included anyway... | |
| 283 | |
| 284 // Note that VT_UNKNOWN must not be the last element in the array; otherwise | |
| 285 // CComVariant will attempt to call Release() on a NULL pointer. | |
| 286 const VARTYPE kUnsupportedSimpleTypes[] = { | |
| 287 VT_I2, VT_R4, VT_CY, VT_DATE, VT_ERROR, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL, | |
| 288 VT_RECORD, VT_I1, VT_UI1, VT_UI2, VT_I8, VT_UI8, VT_INT, VT_UINT, VT_BYREF | |
| 289 }; | |
| 290 for (int i = 0; i < arraysize(kUnsupportedSimpleTypes); ++i) { | |
| 291 ExpectAsserts expect_asserts; | |
| 292 V_VT(&variant_) = kUnsupportedSimpleTypes[i]; | |
| 293 INT32_TO_NPVARIANT(42, np_variant_); | |
| 294 TestV2NPV(); | |
| 295 EXPECT_TRUE(NPVARIANT_IS_VOID(np_variant_)); | |
| 296 } | |
| 297 | |
| 298 // Compound modifiers. | |
| 299 const VARTYPE kCompoundModifiers[] = { | |
| 300 VT_ARRAY, VT_BYREF, VT_ARRAY | VT_BYREF | |
| 301 }; | |
| 302 // Compound types. | |
| 303 const VARTYPE kCompoundableTypes[] = { | |
| 304 VT_I2, VT_I4, VT_R4, VT_R8, VT_CY, VT_DATE, VT_BSTR, VT_DISPATCH, VT_ERROR, | |
| 305 VT_BOOL, VT_VARIANT, VT_UNKNOWN, VT_DECIMAL, VT_RECORD, VT_I1, VT_UI1, | |
| 306 VT_UI2, VT_UI4, VT_I8, VT_UI8, VT_INT, VT_UINT | |
| 307 }; | |
| 308 | |
| 309 for (int i = 0; i < arraysize(kCompoundModifiers); ++i) { | |
| 310 for (int j = 0; j < arraysize(kCompoundableTypes); ++j) { | |
| 311 ExpectAsserts expect_asserts; | |
| 312 V_VT(&variant_) = kCompoundModifiers[i] | kCompoundableTypes[j]; | |
| 313 INT32_TO_NPVARIANT(42, np_variant_); | |
| 314 TestV2NPV(); | |
| 315 EXPECT_TRUE(NPVARIANT_IS_VOID(np_variant_)); | |
| 316 } | |
| 317 } | |
| 318 } | |
| 319 | |
| 320 } // namespace omaha | |
| OLD | NEW |