1 // Copyright 2019 The Chromium Authors
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 "base/win/map.h"
6
7 #include <windows.foundation.h>
8
9 #include <utility>
10
11 #include "base/memory/raw_ptr.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/win/core_winrt_util.h"
14 #include "base/win/hstring_reference.h"
15 #include "base/win/scoped_hstring.h"
16 #include "base/win/scoped_winrt_initializer.h"
17 #include "testing/gtest/include/gtest/gtest.h"
18
19 namespace ABI::Windows::Foundation::Collections {
20
21 // Add missing template specializations (since UWP doesn't provide them):
22
23 // Map<int, double> specializations:
24 template <>
25 struct __declspec(uuid("34784dd6-b37b-4680-b391-899be4f755b6"))
26 IKeyValuePair<int, double> : IKeyValuePair_impl<int, double> {};
27
28 template <>
29 struct __declspec(uuid("c00bd9bd-cce5-46d6-9dc7-f03067e6d523"))
30 IMap<int, double> : IMap_impl<int, double> {};
31
32 template <>
33 struct __declspec(uuid("30e075af-9ba2-4562-9f10-a13a0e57ca5b"))
34 IMapView<int, double> : IMapView_impl<int, double> {};
35
36 template <>
37 struct __declspec(uuid("0a0e8ed6-7deb-4fd4-8033-38d270c69301"))
38 IObservableMap<int, double> : IObservableMap_impl<int, double> {};
39
40 template <>
41 struct __declspec(uuid("f41f9179-9c95-4755-af55-929a250fc0aa"))
42 IMapChangedEventArgs<int> : IMapChangedEventArgs_impl<int> {};
43
44 template <>
45 struct __declspec(uuid("79196029-07f6-47c6-9933-9ac3a04e7731"))
46 MapChangedEventHandler<int, double>
47 : MapChangedEventHandler_impl<int, double> {};
48
49 template <>
50 struct __declspec(uuid("bfd254c3-5ede-4f8f-9e48-3636347f6fe0"))
51 IIterable<IKeyValuePair<int, double>*>
52 : IIterable_impl<IKeyValuePair<int, double>*> {};
53
54 template <>
55 struct __declspec(uuid("6bb5c7ff-964e-469f-87d3-42daaea8e58d"))
56 IIterator<IKeyValuePair<int, double>*>
57 : IIterator_impl<IKeyValuePair<int, double>*> {};
58
59 template <>
60 struct __declspec(uuid("7d27014c-8df7-4977-bf98-b0c821f5f988"))
61 IVector<IKeyValuePair<int, double>*>
62 : IVector_impl<IKeyValuePair<int, double>*> {};
63
64 template <>
65 struct __declspec(uuid("d33b7a5c-9da6-4a6a-8b2e-e08cc0240d77"))
66 IVectorView<IKeyValuePair<int, double>*>
67 : IVectorView_impl<IKeyValuePair<int, double>*> {};
68
69 template <>
70 struct __declspec(uuid("e5b0d7f2-915d-4831-9a04-466fed63cfa0"))
71 VectorChangedEventHandler<IKeyValuePair<int, double>*>
72 : VectorChangedEventHandler_impl<IKeyValuePair<int, double>*> {};
73
74 template <>
75 struct __declspec(uuid("27c3ee04-457f-42dd-9556-8f7c4994d7af"))
76 IObservableVector<IKeyValuePair<int, double>*>
77 : IObservableVector_impl<IKeyValuePair<int, double>*> {};
78
79 // Map<Uri*, Uri*> specializations:
80 template <>
81 struct __declspec(uuid("c03984bc-b800-43e4-a36e-3c8c4a34c005")) IMap<Uri*, Uri*>
82 : IMap_impl<Uri*, Uri*> {};
83
84 template <>
85 struct __declspec(uuid("93ec9c52-1b0b-4fd8-ab5a-f6ea32db0e35"))
86 IMapView<Uri*, Uri*> : IMapView_impl<Uri*, Uri*> {};
87
88 template <>
89 struct __declspec(uuid("9b711c83-5f01-4604-9e01-3d586b3f9cdd"))
90 IObservableMap<Uri*, Uri*> : IObservableMap_impl<Uri*, Uri*> {};
91
92 template <>
93 struct __declspec(uuid("f41f9179-9c95-4755-af55-929a250fc0aa"))
94 IMapChangedEventArgs<Uri*> : IMapChangedEventArgs_impl<Uri*> {};
95
96 template <>
97 struct __declspec(uuid("6d758124-f99a-47e7-ab74-7cff7359b206"))
98 MapChangedEventHandler<Uri*, Uri*>
99 : MapChangedEventHandler_impl<Uri*, Uri*> {};
100
101 template <>
102 struct __declspec(uuid("8b270b8a-d74b-459b-9933-81cb234d7c5e"))
103 IKeyValuePair<Uri*, Uri*> : IKeyValuePair_impl<Uri*, Uri*> {};
104
105 template <>
106 struct __declspec(uuid("6368bcea-dfbc-4847-ba50-9e217fc2d5c3"))
107 IIterable<IKeyValuePair<Uri*, Uri*>*>
108 : IIterable_impl<IKeyValuePair<Uri*, Uri*>*> {};
109
110 template <>
111 struct __declspec(uuid("7653cf9f-9d0b-46d3-882e-4c0afb209333"))
112 IIterator<IKeyValuePair<Uri*, Uri*>*>
113 : IIterator_impl<IKeyValuePair<Uri*, Uri*>*> {};
114
115 template <>
116 struct __declspec(uuid("98c3f5a7-237d-494b-ba89-4a49368d5491"))
117 IVector<IKeyValuePair<Uri*, Uri*>*>
118 : IVector_impl<IKeyValuePair<Uri*, Uri*>*> {};
119
120 template <>
121 struct __declspec(uuid("2cfc2617-7c88-4482-8158-97bf7cc458d7"))
122 IVectorView<IKeyValuePair<Uri*, Uri*>*>
123 : IVectorView_impl<IKeyValuePair<Uri*, Uri*>*> {};
124
125 template <>
126 struct __declspec(uuid("bb581e03-3ee7-4c01-8035-4f581c5e91f5"))
127 VectorChangedEventHandler<IKeyValuePair<Uri*, Uri*>*>
128 : VectorChangedEventHandler_impl<IKeyValuePair<Uri*, Uri*>*> {};
129
130 template <>
131 struct __declspec(uuid("fb0bd692-34c3-4242-a085-58ed71e8ea6b"))
132 IObservableVector<IKeyValuePair<Uri*, Uri*>*>
133 : IObservableVector_impl<IKeyValuePair<Uri*, Uri*>*> {};
134
135 // Map<HSTRING*, IInspectable*> specializations:
136 template <>
137 struct __declspec(uuid("c6682be1-963c-4101-85aa-63db583eb0d5"))
138 IVector<IKeyValuePair<HSTRING, IInspectable*>*>
139 : IVector_impl<IKeyValuePair<HSTRING, IInspectable*>*> {};
140
141 template <>
142 struct __declspec(uuid("868e5342-49c8-478f-af0f-1691e1bbbb7c"))
143 IVectorView<IKeyValuePair<HSTRING, IInspectable*>*>
144 : IVectorView_impl<IKeyValuePair<HSTRING, IInspectable*>*> {};
145
146 template <>
147 struct __declspec(uuid("cd99b82f-a768-405f-9123-be509146fef8"))
148 VectorChangedEventHandler<IKeyValuePair<HSTRING, IInspectable*>*>
149 : VectorChangedEventHandler_impl<IKeyValuePair<HSTRING, IInspectable*>*> {};
150
151 template <>
152 struct __declspec(uuid("079e2180-0c7a-4508-85ff-7a5f2b29b92b"))
153 IObservableVector<IKeyValuePair<HSTRING, IInspectable*>*>
154 : IObservableVector_impl<IKeyValuePair<HSTRING, IInspectable*>*> {};
155
156 } // namespace ABI::Windows::Foundation::Collections
157
158 namespace base::win {
159
160 namespace {
161
162 using ABI::Windows::Foundation::IPropertyValue;
163 using ABI::Windows::Foundation::IPropertyValueStatics;
164 using ABI::Windows::Foundation::Uri;
165 using ABI::Windows::Foundation::Collections::CollectionChange;
166 using ABI::Windows::Foundation::Collections::CollectionChange_ItemChanged;
167 using ABI::Windows::Foundation::Collections::CollectionChange_ItemInserted;
168 using ABI::Windows::Foundation::Collections::CollectionChange_ItemRemoved;
169 using ABI::Windows::Foundation::Collections::CollectionChange_Reset;
170 using ABI::Windows::Foundation::Collections::IIterator;
171 using ABI::Windows::Foundation::Collections::IKeyValuePair;
172 using ABI::Windows::Foundation::Collections::IMapChangedEventArgs;
173 using ABI::Windows::Foundation::Collections::IMapView;
174 using ABI::Windows::Foundation::Collections::IObservableMap;
175 using ABI::Windows::Foundation::Collections::MapChangedEventHandler;
176 using Microsoft::WRL::ClassicCom;
177 using Microsoft::WRL::ComPtr;
178 using Microsoft::WRL::InhibitRoOriginateError;
179 using Microsoft::WRL::Make;
180 using Microsoft::WRL::RuntimeClass;
181 using Microsoft::WRL::RuntimeClassFlags;
182
183 const wchar_t kTestKey[] = L"Test key";
184 const wchar_t kTestValue[] = L"Test value";
185
186 const std::map<int, double, internal::Less> g_one{{1, 10.7}};
187 const std::map<int, double, internal::Less> g_two{{1, 10.7}, {2, 20.3}};
188
GetPropertyValueStaticsActivationFactory(IPropertyValueStatics ** statics)189 HRESULT GetPropertyValueStaticsActivationFactory(
190 IPropertyValueStatics** statics) {
191 return base::win::GetActivationFactory<
192 IPropertyValueStatics, RuntimeClass_Windows_Foundation_PropertyValue>(
193 statics);
194 }
195
196 template <typename K, typename V>
197 class FakeMapChangedEventHandler
198 : public RuntimeClass<
199 RuntimeClassFlags<ClassicCom | InhibitRoOriginateError>,
200 MapChangedEventHandler<K, V>> {
201 public:
FakeMapChangedEventHandler(ComPtr<IObservableMap<K,V>> map)202 explicit FakeMapChangedEventHandler(ComPtr<IObservableMap<K, V>> map)
203 : map_(std::move(map)) {
204 EXPECT_HRESULT_SUCCEEDED(map_->add_MapChanged(this, &token_));
205 }
206
~FakeMapChangedEventHandler()207 ~FakeMapChangedEventHandler() override {
208 EXPECT_HRESULT_SUCCEEDED(map_->remove_MapChanged(token_));
209 }
210
211 // MapChangedEventHandler:
Invoke(IObservableMap<K,V> * sender,IMapChangedEventArgs<K> * e)212 IFACEMETHODIMP Invoke(IObservableMap<K, V>* sender,
213 IMapChangedEventArgs<K>* e) {
214 sender_ = sender;
215 EXPECT_HRESULT_SUCCEEDED(e->get_CollectionChange(&change_));
216 EXPECT_HRESULT_SUCCEEDED(e->get_Key(&key_));
217 return S_OK;
218 }
219
sender()220 IObservableMap<K, V>* sender() { return sender_; }
change()221 CollectionChange change() { return change_; }
key() const222 K key() const { return key_; }
223
224 private:
225 ComPtr<IObservableMap<K, V>> map_;
226 EventRegistrationToken token_;
227 raw_ptr<IObservableMap<K, V>> sender_ = nullptr;
228 CollectionChange change_ = CollectionChange_Reset;
229 K key_ = 0;
230 };
231
232 } // namespace
233
TEST(MapTest,Lookup_Empty)234 TEST(MapTest, Lookup_Empty) {
235 auto map = Make<Map<int, double>>();
236 double value;
237 HRESULT hr = map->Lookup(1, &value);
238 EXPECT_EQ(E_BOUNDS, hr);
239 hr = map->Lookup(2, &value);
240 EXPECT_EQ(E_BOUNDS, hr);
241 }
242
TEST(MapTest,Lookup_One)243 TEST(MapTest, Lookup_One) {
244 auto map = Make<Map<int, double>>(g_one);
245 double value;
246 HRESULT hr = map->Lookup(1, &value);
247 EXPECT_EQ(S_OK, hr);
248 EXPECT_EQ(10.7, value);
249 hr = map->Lookup(2, &value);
250 EXPECT_EQ(E_BOUNDS, hr);
251 }
252
TEST(MapTest,Lookup_Two)253 TEST(MapTest, Lookup_Two) {
254 auto map = Make<Map<int, double>>(g_two);
255 double value;
256 HRESULT hr = map->Lookup(1, &value);
257 EXPECT_EQ(S_OK, hr);
258 EXPECT_EQ(10.7, value);
259 hr = map->Lookup(2, &value);
260 EXPECT_EQ(S_OK, hr);
261 EXPECT_EQ(20.3, value);
262 }
263
TEST(MapTest,get_Size_Empty)264 TEST(MapTest, get_Size_Empty) {
265 auto map = Make<Map<int, double>>();
266 unsigned int size;
267 HRESULT hr = map->get_Size(&size);
268 EXPECT_HRESULT_SUCCEEDED(hr);
269 EXPECT_EQ(0u, size);
270 }
271
TEST(MapTest,get_Size_One)272 TEST(MapTest, get_Size_One) {
273 auto map = Make<Map<int, double>>(g_one);
274 unsigned int size;
275 HRESULT hr = map->get_Size(&size);
276 EXPECT_HRESULT_SUCCEEDED(hr);
277 EXPECT_EQ(1u, size);
278 }
279
TEST(MapTest,get_Size_Two)280 TEST(MapTest, get_Size_Two) {
281 auto map = Make<Map<int, double>>(g_two);
282 unsigned int size;
283 HRESULT hr = map->get_Size(&size);
284 EXPECT_HRESULT_SUCCEEDED(hr);
285 EXPECT_EQ(2u, size);
286 }
287
TEST(MapTest,HasKey_Empty)288 TEST(MapTest, HasKey_Empty) {
289 auto map = Make<Map<int, double>>();
290 boolean found;
291 HRESULT hr = map->HasKey(1, &found);
292 EXPECT_HRESULT_SUCCEEDED(hr);
293 EXPECT_FALSE(found);
294 }
295
TEST(MapTest,HasKey_One)296 TEST(MapTest, HasKey_One) {
297 auto map = Make<Map<int, double>>(g_one);
298 boolean found;
299 HRESULT hr = map->HasKey(1, &found);
300 EXPECT_HRESULT_SUCCEEDED(hr);
301 EXPECT_TRUE(found);
302 hr = map->HasKey(2, &found);
303 EXPECT_HRESULT_SUCCEEDED(hr);
304 EXPECT_FALSE(found);
305 }
306
TEST(MapTest,HasKey_Two)307 TEST(MapTest, HasKey_Two) {
308 auto map = Make<Map<int, double>>(g_two);
309 boolean found;
310 HRESULT hr = map->HasKey(1, &found);
311 EXPECT_HRESULT_SUCCEEDED(hr);
312 EXPECT_TRUE(found);
313 hr = map->HasKey(2, &found);
314 EXPECT_HRESULT_SUCCEEDED(hr);
315 EXPECT_TRUE(found);
316 }
317
TEST(MapTest,GetView)318 TEST(MapTest, GetView) {
319 auto map = Make<Map<int, double>>(g_two);
320 ComPtr<IMapView<int, double>> view;
321 HRESULT hr = map->GetView(&view);
322 EXPECT_HRESULT_SUCCEEDED(hr);
323
324 double value;
325 hr = view->Lookup(1, &value);
326 EXPECT_EQ(S_OK, hr);
327 EXPECT_EQ(10.7, value);
328 hr = view->Lookup(2, &value);
329 EXPECT_EQ(S_OK, hr);
330 EXPECT_EQ(20.3, value);
331
332 unsigned int size;
333 hr = view->get_Size(&size);
334 EXPECT_HRESULT_SUCCEEDED(hr);
335 EXPECT_EQ(2u, size);
336
337 boolean found;
338 hr = view->HasKey(1, &found);
339 EXPECT_HRESULT_SUCCEEDED(hr);
340 EXPECT_TRUE(found);
341 hr = view->HasKey(2, &found);
342 EXPECT_HRESULT_SUCCEEDED(hr);
343 EXPECT_TRUE(found);
344
345 // The view is supposed to be a snapshot of the map when it's created.
346 // Further modifications to the map will invalidate the view.
347 boolean replaced;
348 hr = map->Insert(3, 11.2, &replaced);
349 EXPECT_HRESULT_SUCCEEDED(hr);
350 EXPECT_FALSE(replaced);
351
352 hr = view->Lookup(1, &value);
353 EXPECT_EQ(E_CHANGED_STATE, hr);
354
355 hr = view->get_Size(&size);
356 EXPECT_EQ(E_CHANGED_STATE, hr);
357
358 hr = view->HasKey(1, &found);
359 EXPECT_EQ(E_CHANGED_STATE, hr);
360 }
361
TEST(MapTest,Insert_Empty)362 TEST(MapTest, Insert_Empty) {
363 auto map = Make<Map<int, double>>();
364 auto handler = Make<FakeMapChangedEventHandler<int, double>>(map.Get());
365 boolean replaced;
366 HRESULT hr = map->Insert(1, 11.2, &replaced);
367 EXPECT_HRESULT_SUCCEEDED(hr);
368 EXPECT_FALSE(replaced);
369 EXPECT_EQ(map.Get(), handler->sender());
370 EXPECT_EQ(CollectionChange_ItemInserted, handler->change());
371 EXPECT_EQ(1, handler->key());
372 double value;
373 hr = map->Lookup(1, &value);
374 EXPECT_EQ(S_OK, hr);
375 EXPECT_EQ(11.2, value);
376 }
377
TEST(MapTest,Insert_One)378 TEST(MapTest, Insert_One) {
379 auto map = Make<Map<int, double>>(g_one);
380 auto handler = Make<FakeMapChangedEventHandler<int, double>>(map.Get());
381 double value;
382 HRESULT hr = map->Lookup(1, &value);
383 EXPECT_EQ(S_OK, hr);
384 EXPECT_EQ(10.7, value);
385 boolean replaced;
386 hr = map->Insert(1, 11.2, &replaced);
387 EXPECT_HRESULT_SUCCEEDED(hr);
388 EXPECT_TRUE(replaced);
389 EXPECT_EQ(map.Get(), handler->sender());
390 EXPECT_EQ(CollectionChange_ItemChanged, handler->change());
391 EXPECT_EQ(1, handler->key());
392 hr = map->Lookup(1, &value);
393 EXPECT_EQ(S_OK, hr);
394 EXPECT_EQ(11.2, value);
395 }
396
TEST(MapTest,Remove_One)397 TEST(MapTest, Remove_One) {
398 auto map = Make<Map<int, double>>(g_one);
399 auto handler = Make<FakeMapChangedEventHandler<int, double>>(map.Get());
400 double value;
401 HRESULT hr = map->Lookup(1, &value);
402 EXPECT_EQ(S_OK, hr);
403 EXPECT_EQ(10.7, value);
404 hr = map->Remove(1);
405 EXPECT_EQ(S_OK, hr);
406 EXPECT_EQ(map.Get(), handler->sender());
407 EXPECT_EQ(CollectionChange_ItemRemoved, handler->change());
408 EXPECT_EQ(1, handler->key());
409 hr = map->Lookup(1, &value);
410 EXPECT_EQ(E_BOUNDS, hr);
411 }
412
TEST(MapTest,Clear)413 TEST(MapTest, Clear) {
414 auto map = Make<Map<int, double>>(g_one);
415 auto handler = Make<FakeMapChangedEventHandler<int, double>>(map.Get());
416 HRESULT hr = map->Clear();
417 EXPECT_EQ(map.Get(), handler->sender());
418 EXPECT_EQ(CollectionChange_Reset, handler->change());
419 EXPECT_EQ(0, handler->key());
420 unsigned int size;
421 hr = map->get_Size(&size);
422 EXPECT_HRESULT_SUCCEEDED(hr);
423 EXPECT_EQ(0u, size);
424 }
425
426 // Uri* is an AggregateType which ABI representation is IUriRuntimeClass*.
TEST(MapTest,ConstructWithAggregateTypes)427 TEST(MapTest, ConstructWithAggregateTypes) {
428 auto map = Make<Map<Uri*, Uri*>>();
429 unsigned size;
430 HRESULT hr = map->get_Size(&size);
431 EXPECT_HRESULT_SUCCEEDED(hr);
432 EXPECT_EQ(0u, size);
433 }
434
TEST(MapTest,First)435 TEST(MapTest, First) {
436 auto map = Make<Map<int, double>>(g_two);
437 ComPtr<IIterator<IKeyValuePair<int, double>*>> iterator;
438
439 // Test iteration.
440 HRESULT hr = map->First(&iterator);
441 EXPECT_HRESULT_SUCCEEDED(hr);
442 boolean has_current;
443 hr = iterator->get_HasCurrent(&has_current);
444 EXPECT_HRESULT_SUCCEEDED(hr);
445 EXPECT_TRUE(has_current);
446 ComPtr<IKeyValuePair<int, double>> current;
447 hr = iterator->get_Current(¤t);
448 EXPECT_HRESULT_SUCCEEDED(hr);
449 int key;
450 hr = current->get_Key(&key);
451 EXPECT_HRESULT_SUCCEEDED(hr);
452 EXPECT_EQ(1, key);
453 double value;
454 hr = current->get_Value(&value);
455 EXPECT_HRESULT_SUCCEEDED(hr);
456 EXPECT_EQ(10.7, value);
457 hr = iterator->MoveNext(&has_current);
458 EXPECT_HRESULT_SUCCEEDED(hr);
459 EXPECT_TRUE(has_current);
460 hr = iterator->get_Current(¤t);
461 EXPECT_HRESULT_SUCCEEDED(hr);
462 hr = current->get_Key(&key);
463 EXPECT_HRESULT_SUCCEEDED(hr);
464 EXPECT_EQ(2, key);
465 hr = current->get_Value(&value);
466 EXPECT_HRESULT_SUCCEEDED(hr);
467 EXPECT_EQ(20.3, value);
468 hr = iterator->MoveNext(&has_current);
469 EXPECT_HRESULT_SUCCEEDED(hr);
470 EXPECT_FALSE(has_current);
471 hr = iterator->get_Current(¤t);
472 EXPECT_FALSE(SUCCEEDED(hr));
473 EXPECT_EQ(E_BOUNDS, hr);
474 hr = iterator->MoveNext(&has_current);
475 EXPECT_FALSE(SUCCEEDED(hr));
476 EXPECT_EQ(E_BOUNDS, hr);
477 EXPECT_FALSE(has_current);
478
479 // Test invalidation.
480 hr = map->First(&iterator);
481 EXPECT_HRESULT_SUCCEEDED(hr);
482 hr = iterator->get_HasCurrent(&has_current);
483 EXPECT_HRESULT_SUCCEEDED(hr);
484 EXPECT_TRUE(has_current);
485 boolean replaced;
486 hr = map->Insert(3, 11.2, &replaced);
487 EXPECT_HRESULT_SUCCEEDED(hr);
488 EXPECT_FALSE(replaced);
489 hr = iterator->get_HasCurrent(&has_current);
490 EXPECT_EQ(E_CHANGED_STATE, hr);
491 hr = iterator->MoveNext(&has_current);
492 EXPECT_EQ(E_CHANGED_STATE, hr);
493 }
494
TEST(MapTest,Properties)495 TEST(MapTest, Properties) {
496 // This test case validates Map against Windows property key system,
497 // which is used to store WinRT device properties.
498 ScopedWinrtInitializer winrt_initializer;
499 ASSERT_TRUE(winrt_initializer.Succeeded());
500
501 auto map = Make<Map<HSTRING, IInspectable*>>();
502
503 ComPtr<IPropertyValueStatics> property_value_statics;
504 HRESULT hr =
505 GetPropertyValueStaticsActivationFactory(&property_value_statics);
506 EXPECT_HRESULT_SUCCEEDED(hr);
507
508 base::win::HStringReference value_stringref_inserted(kTestValue);
509 ComPtr<IPropertyValue> value_inserted;
510 hr = property_value_statics->CreateString(value_stringref_inserted.Get(),
511 &value_inserted);
512 EXPECT_HRESULT_SUCCEEDED(hr);
513
514 base::win::HStringReference key_stringref_inserted(kTestKey);
515 boolean replaced;
516 hr = map->Insert(key_stringref_inserted.Get(), value_inserted.Get(),
517 &replaced);
518 EXPECT_HRESULT_SUCCEEDED(hr);
519
520 base::win::HStringReference key_stringref_lookedup(kTestKey);
521 ComPtr<IInspectable> value_inspectable_lookedup;
522 hr = map->Lookup(key_stringref_lookedup.Get(), &value_inspectable_lookedup);
523 EXPECT_HRESULT_SUCCEEDED(hr);
524
525 ComPtr<IPropertyValue> value_lookedup;
526 hr = value_inspectable_lookedup.As(&value_lookedup);
527 EXPECT_HRESULT_SUCCEEDED(hr);
528
529 HSTRING value_string_lookedup;
530 hr = value_lookedup->GetString(&value_string_lookedup);
531 EXPECT_HRESULT_SUCCEEDED(hr);
532
533 auto value_stringref_lookedup = ScopedHString(value_string_lookedup);
534 EXPECT_EQ(kTestValue, value_stringref_lookedup.Get());
535 }
536
537 } // namespace base::win
538