1 // Copyright 2019 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 "base/win/map.h"
6 
7 #include <windows.foundation.h>
8 
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/win/core_winrt_util.h"
11 #include "base/win/hstring_reference.h"
12 #include "base/win/scoped_hstring.h"
13 #include "base/win/windows_version.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15 
16 namespace ABI {
17 namespace Windows {
18 namespace Foundation {
19 namespace 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 Collections
157 }  // namespace Foundation
158 }  // namespace Windows
159 }  // namespace ABI
160 
161 namespace base {
162 namespace win {
163 
164 namespace {
165 
166 using ABI::Windows::Foundation::IPropertyValue;
167 using ABI::Windows::Foundation::IPropertyValueStatics;
168 using ABI::Windows::Foundation::Uri;
169 using ABI::Windows::Foundation::Collections::CollectionChange;
170 using ABI::Windows::Foundation::Collections::CollectionChange_ItemChanged;
171 using ABI::Windows::Foundation::Collections::CollectionChange_ItemInserted;
172 using ABI::Windows::Foundation::Collections::CollectionChange_ItemRemoved;
173 using ABI::Windows::Foundation::Collections::CollectionChange_Reset;
174 using ABI::Windows::Foundation::Collections::IIterator;
175 using ABI::Windows::Foundation::Collections::IKeyValuePair;
176 using ABI::Windows::Foundation::Collections::IMapChangedEventArgs;
177 using ABI::Windows::Foundation::Collections::IMapView;
178 using ABI::Windows::Foundation::Collections::IObservableMap;
179 using ABI::Windows::Foundation::Collections::MapChangedEventHandler;
180 using Microsoft::WRL::ClassicCom;
181 using Microsoft::WRL::ComPtr;
182 using Microsoft::WRL::InhibitRoOriginateError;
183 using Microsoft::WRL::Make;
184 using Microsoft::WRL::RuntimeClass;
185 using Microsoft::WRL::RuntimeClassFlags;
186 
187 const wchar_t kTestKey[] = L"Test key";
188 const wchar_t kTestValue[] = L"Test value";
189 
190 const std::map<int, double, internal::Less> g_one{{1, 10.7}};
191 const std::map<int, double, internal::Less> g_two{{1, 10.7}, {2, 20.3}};
192 
ResolveCoreWinRT()193 bool ResolveCoreWinRT() {
194   return base::win::ResolveCoreWinRTDelayload() &&
195          base::win::ScopedHString::ResolveCoreWinRTStringDelayload() &&
196          base::win::HStringReference::ResolveCoreWinRTStringDelayload();
197 }
198 
GetPropertyValueStaticsActivationFactory(IPropertyValueStatics ** statics)199 HRESULT GetPropertyValueStaticsActivationFactory(
200     IPropertyValueStatics** statics) {
201   return base::win::GetActivationFactory<
202       IPropertyValueStatics, RuntimeClass_Windows_Foundation_PropertyValue>(
203       statics);
204 }
205 
206 template <typename K, typename V>
207 class FakeMapChangedEventHandler
208     : public RuntimeClass<
209           RuntimeClassFlags<ClassicCom | InhibitRoOriginateError>,
210           MapChangedEventHandler<K, V>> {
211  public:
FakeMapChangedEventHandler(ComPtr<IObservableMap<K,V>> map)212   explicit FakeMapChangedEventHandler(ComPtr<IObservableMap<K, V>> map)
213       : map_(std::move(map)) {
214     EXPECT_HRESULT_SUCCEEDED(map_->add_MapChanged(this, &token_));
215   }
216 
~FakeMapChangedEventHandler()217   ~FakeMapChangedEventHandler() override {
218     EXPECT_HRESULT_SUCCEEDED(map_->remove_MapChanged(token_));
219   }
220 
221   // MapChangedEventHandler:
Invoke(IObservableMap<K,V> * sender,IMapChangedEventArgs<K> * e)222   IFACEMETHODIMP Invoke(IObservableMap<K, V>* sender,
223                         IMapChangedEventArgs<K>* e) {
224     sender_ = sender;
225     EXPECT_HRESULT_SUCCEEDED(e->get_CollectionChange(&change_));
226     EXPECT_HRESULT_SUCCEEDED(e->get_Key(&key_));
227     return S_OK;
228   }
229 
sender()230   IObservableMap<K, V>* sender() { return sender_; }
change()231   CollectionChange change() { return change_; }
key() const232   K key() const { return key_; }
233 
234  private:
235   ComPtr<IObservableMap<K, V>> map_;
236   EventRegistrationToken token_;
237   IObservableMap<K, V>* sender_ = nullptr;
238   CollectionChange change_ = CollectionChange_Reset;
239   K key_ = 0;
240 };
241 
242 }  // namespace
243 
TEST(MapTest,Lookup_Empty)244 TEST(MapTest, Lookup_Empty) {
245   auto map = Make<Map<int, double>>();
246   double value;
247   HRESULT hr = map->Lookup(1, &value);
248   EXPECT_EQ(E_BOUNDS, hr);
249   hr = map->Lookup(2, &value);
250   EXPECT_EQ(E_BOUNDS, hr);
251 }
252 
TEST(MapTest,Lookup_One)253 TEST(MapTest, Lookup_One) {
254   auto map = Make<Map<int, double>>(g_one);
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(E_BOUNDS, hr);
261 }
262 
TEST(MapTest,Lookup_Two)263 TEST(MapTest, Lookup_Two) {
264   auto map = Make<Map<int, double>>(g_two);
265   double value;
266   HRESULT hr = map->Lookup(1, &value);
267   EXPECT_EQ(S_OK, hr);
268   EXPECT_EQ(10.7, value);
269   hr = map->Lookup(2, &value);
270   EXPECT_EQ(S_OK, hr);
271   EXPECT_EQ(20.3, value);
272 }
273 
TEST(MapTest,get_Size_Empty)274 TEST(MapTest, get_Size_Empty) {
275   auto map = Make<Map<int, double>>();
276   unsigned int size;
277   HRESULT hr = map->get_Size(&size);
278   EXPECT_HRESULT_SUCCEEDED(hr);
279   EXPECT_EQ(0u, size);
280 }
281 
TEST(MapTest,get_Size_One)282 TEST(MapTest, get_Size_One) {
283   auto map = Make<Map<int, double>>(g_one);
284   unsigned int size;
285   HRESULT hr = map->get_Size(&size);
286   EXPECT_HRESULT_SUCCEEDED(hr);
287   EXPECT_EQ(1u, size);
288 }
289 
TEST(MapTest,get_Size_Two)290 TEST(MapTest, get_Size_Two) {
291   auto map = Make<Map<int, double>>(g_two);
292   unsigned int size;
293   HRESULT hr = map->get_Size(&size);
294   EXPECT_HRESULT_SUCCEEDED(hr);
295   EXPECT_EQ(2u, size);
296 }
297 
TEST(MapTest,HasKey_Empty)298 TEST(MapTest, HasKey_Empty) {
299   auto map = Make<Map<int, double>>();
300   boolean found;
301   HRESULT hr = map->HasKey(1, &found);
302   EXPECT_HRESULT_SUCCEEDED(hr);
303   EXPECT_FALSE(found);
304 }
305 
TEST(MapTest,HasKey_One)306 TEST(MapTest, HasKey_One) {
307   auto map = Make<Map<int, double>>(g_one);
308   boolean found;
309   HRESULT hr = map->HasKey(1, &found);
310   EXPECT_HRESULT_SUCCEEDED(hr);
311   EXPECT_TRUE(found);
312   hr = map->HasKey(2, &found);
313   EXPECT_HRESULT_SUCCEEDED(hr);
314   EXPECT_FALSE(found);
315 }
316 
TEST(MapTest,HasKey_Two)317 TEST(MapTest, HasKey_Two) {
318   auto map = Make<Map<int, double>>(g_two);
319   boolean found;
320   HRESULT hr = map->HasKey(1, &found);
321   EXPECT_HRESULT_SUCCEEDED(hr);
322   EXPECT_TRUE(found);
323   hr = map->HasKey(2, &found);
324   EXPECT_HRESULT_SUCCEEDED(hr);
325   EXPECT_TRUE(found);
326 }
327 
TEST(MapTest,GetView)328 TEST(MapTest, GetView) {
329   auto map = Make<Map<int, double>>(g_two);
330   ComPtr<IMapView<int, double>> view;
331   HRESULT hr = map->GetView(&view);
332   EXPECT_HRESULT_SUCCEEDED(hr);
333 
334   double value;
335   hr = view->Lookup(1, &value);
336   EXPECT_EQ(S_OK, hr);
337   EXPECT_EQ(10.7, value);
338   hr = view->Lookup(2, &value);
339   EXPECT_EQ(S_OK, hr);
340   EXPECT_EQ(20.3, value);
341 
342   unsigned int size;
343   hr = view->get_Size(&size);
344   EXPECT_HRESULT_SUCCEEDED(hr);
345   EXPECT_EQ(2u, size);
346 
347   boolean found;
348   hr = view->HasKey(1, &found);
349   EXPECT_HRESULT_SUCCEEDED(hr);
350   EXPECT_TRUE(found);
351   hr = view->HasKey(2, &found);
352   EXPECT_HRESULT_SUCCEEDED(hr);
353   EXPECT_TRUE(found);
354 
355   // The view is supposed to be a snapshot of the map when it's created.
356   // Further modifications to the map will invalidate the view.
357   boolean replaced;
358   hr = map->Insert(3, 11.2, &replaced);
359   EXPECT_HRESULT_SUCCEEDED(hr);
360   EXPECT_FALSE(replaced);
361 
362   hr = view->Lookup(1, &value);
363   EXPECT_EQ(E_CHANGED_STATE, hr);
364 
365   hr = view->get_Size(&size);
366   EXPECT_EQ(E_CHANGED_STATE, hr);
367 
368   hr = view->HasKey(1, &found);
369   EXPECT_EQ(E_CHANGED_STATE, hr);
370 }
371 
TEST(MapTest,Insert_Empty)372 TEST(MapTest, Insert_Empty) {
373   auto map = Make<Map<int, double>>();
374   auto handler = Make<FakeMapChangedEventHandler<int, double>>(map.Get());
375   boolean replaced;
376   HRESULT hr = map->Insert(1, 11.2, &replaced);
377   EXPECT_HRESULT_SUCCEEDED(hr);
378   EXPECT_FALSE(replaced);
379   EXPECT_EQ(map.Get(), handler->sender());
380   EXPECT_EQ(CollectionChange_ItemInserted, handler->change());
381   EXPECT_EQ(1, handler->key());
382   double value;
383   hr = map->Lookup(1, &value);
384   EXPECT_EQ(S_OK, hr);
385   EXPECT_EQ(11.2, value);
386 }
387 
TEST(MapTest,Insert_One)388 TEST(MapTest, Insert_One) {
389   auto map = Make<Map<int, double>>(g_one);
390   auto handler = Make<FakeMapChangedEventHandler<int, double>>(map.Get());
391   double value;
392   HRESULT hr = map->Lookup(1, &value);
393   EXPECT_EQ(S_OK, hr);
394   EXPECT_EQ(10.7, value);
395   boolean replaced;
396   hr = map->Insert(1, 11.2, &replaced);
397   EXPECT_HRESULT_SUCCEEDED(hr);
398   EXPECT_TRUE(replaced);
399   EXPECT_EQ(map.Get(), handler->sender());
400   EXPECT_EQ(CollectionChange_ItemChanged, handler->change());
401   EXPECT_EQ(1, handler->key());
402   hr = map->Lookup(1, &value);
403   EXPECT_EQ(S_OK, hr);
404   EXPECT_EQ(11.2, value);
405 }
406 
TEST(MapTest,Remove_One)407 TEST(MapTest, Remove_One) {
408   auto map = Make<Map<int, double>>(g_one);
409   auto handler = Make<FakeMapChangedEventHandler<int, double>>(map.Get());
410   double value;
411   HRESULT hr = map->Lookup(1, &value);
412   EXPECT_EQ(S_OK, hr);
413   EXPECT_EQ(10.7, value);
414   hr = map->Remove(1);
415   EXPECT_EQ(S_OK, hr);
416   EXPECT_EQ(map.Get(), handler->sender());
417   EXPECT_EQ(CollectionChange_ItemRemoved, handler->change());
418   EXPECT_EQ(1, handler->key());
419   hr = map->Lookup(1, &value);
420   EXPECT_EQ(E_BOUNDS, hr);
421 }
422 
TEST(MapTest,Clear)423 TEST(MapTest, Clear) {
424   auto map = Make<Map<int, double>>(g_one);
425   auto handler = Make<FakeMapChangedEventHandler<int, double>>(map.Get());
426   HRESULT hr = map->Clear();
427   EXPECT_EQ(map.Get(), handler->sender());
428   EXPECT_EQ(CollectionChange_Reset, handler->change());
429   EXPECT_EQ(0, handler->key());
430   unsigned int size;
431   hr = map->get_Size(&size);
432   EXPECT_HRESULT_SUCCEEDED(hr);
433   EXPECT_EQ(0u, size);
434 }
435 
436 // Uri* is an AggregateType which ABI representation is IUriRuntimeClass*.
TEST(MapTest,ConstructWithAggregateTypes)437 TEST(MapTest, ConstructWithAggregateTypes) {
438   auto map = Make<Map<Uri*, Uri*>>();
439   unsigned size;
440   HRESULT hr = map->get_Size(&size);
441   EXPECT_HRESULT_SUCCEEDED(hr);
442   EXPECT_EQ(0u, size);
443 }
444 
TEST(MapTest,First)445 TEST(MapTest, First) {
446   auto map = Make<Map<int, double>>(g_two);
447   ComPtr<IIterator<IKeyValuePair<int, double>*>> iterator;
448 
449   // Test iteration.
450   HRESULT hr = map->First(&iterator);
451   EXPECT_HRESULT_SUCCEEDED(hr);
452   boolean has_current;
453   hr = iterator->get_HasCurrent(&has_current);
454   EXPECT_HRESULT_SUCCEEDED(hr);
455   EXPECT_TRUE(has_current);
456   ComPtr<IKeyValuePair<int, double>> current;
457   hr = iterator->get_Current(&current);
458   EXPECT_HRESULT_SUCCEEDED(hr);
459   int key;
460   hr = current->get_Key(&key);
461   EXPECT_HRESULT_SUCCEEDED(hr);
462   EXPECT_EQ(1, key);
463   double value;
464   hr = current->get_Value(&value);
465   EXPECT_HRESULT_SUCCEEDED(hr);
466   EXPECT_EQ(10.7, value);
467   hr = iterator->MoveNext(&has_current);
468   EXPECT_HRESULT_SUCCEEDED(hr);
469   EXPECT_TRUE(has_current);
470   hr = iterator->get_Current(&current);
471   EXPECT_HRESULT_SUCCEEDED(hr);
472   hr = current->get_Key(&key);
473   EXPECT_HRESULT_SUCCEEDED(hr);
474   EXPECT_EQ(2, key);
475   hr = current->get_Value(&value);
476   EXPECT_HRESULT_SUCCEEDED(hr);
477   EXPECT_EQ(20.3, value);
478   hr = iterator->MoveNext(&has_current);
479   EXPECT_HRESULT_SUCCEEDED(hr);
480   EXPECT_FALSE(has_current);
481   hr = iterator->get_Current(&current);
482   EXPECT_FALSE(SUCCEEDED(hr));
483   EXPECT_EQ(E_BOUNDS, hr);
484   hr = iterator->MoveNext(&has_current);
485   EXPECT_FALSE(SUCCEEDED(hr));
486   EXPECT_EQ(E_BOUNDS, hr);
487   EXPECT_FALSE(has_current);
488 
489   // Test invalidation.
490   hr = map->First(&iterator);
491   EXPECT_HRESULT_SUCCEEDED(hr);
492   hr = iterator->get_HasCurrent(&has_current);
493   EXPECT_HRESULT_SUCCEEDED(hr);
494   EXPECT_TRUE(has_current);
495   boolean replaced;
496   hr = map->Insert(3, 11.2, &replaced);
497   EXPECT_HRESULT_SUCCEEDED(hr);
498   EXPECT_FALSE(replaced);
499   hr = iterator->get_HasCurrent(&has_current);
500   EXPECT_EQ(E_CHANGED_STATE, hr);
501   hr = iterator->MoveNext(&has_current);
502   EXPECT_EQ(E_CHANGED_STATE, hr);
503 }
504 
TEST(MapTest,Properties)505 TEST(MapTest, Properties) {
506   // This test case validates Map against Windows property key system,
507   // which is used to store WinRT device properties.
508   if (GetVersion() < Version::WIN8)
509     return;
510 
511   ASSERT_TRUE(ResolveCoreWinRT());
512   ASSERT_HRESULT_SUCCEEDED(base::win::RoInitialize(RO_INIT_MULTITHREADED));
513 
514   auto map = Make<Map<HSTRING, IInspectable*>>();
515 
516   ComPtr<IPropertyValueStatics> property_value_statics;
517   HRESULT hr =
518       GetPropertyValueStaticsActivationFactory(&property_value_statics);
519   EXPECT_HRESULT_SUCCEEDED(hr);
520 
521   base::win::HStringReference value_stringref_inserted(kTestValue);
522   ComPtr<IPropertyValue> value_inserted;
523   hr = property_value_statics->CreateString(value_stringref_inserted.Get(),
524                                             &value_inserted);
525   EXPECT_HRESULT_SUCCEEDED(hr);
526 
527   base::win::HStringReference key_stringref_inserted(kTestKey);
528   boolean replaced;
529   hr = map->Insert(key_stringref_inserted.Get(), value_inserted.Get(),
530                    &replaced);
531   EXPECT_HRESULT_SUCCEEDED(hr);
532 
533   base::win::HStringReference key_stringref_lookedup(kTestKey);
534   ComPtr<IInspectable> value_inspectable_lookedup;
535   hr = map->Lookup(key_stringref_lookedup.Get(), &value_inspectable_lookedup);
536   EXPECT_HRESULT_SUCCEEDED(hr);
537 
538   ComPtr<IPropertyValue> value_lookedup;
539   hr = value_inspectable_lookedup.As(&value_lookedup);
540   EXPECT_HRESULT_SUCCEEDED(hr);
541 
542   HSTRING value_string_lookedup;
543   hr = value_lookedup->GetString(&value_string_lookedup);
544   EXPECT_HRESULT_SUCCEEDED(hr);
545 
546   auto value_stringref_lookedup = ScopedHString(value_string_lookedup);
547   EXPECT_EQ(kTestValue, value_stringref_lookedup.Get());
548 }
549 
550 }  // namespace win
551 }  // namespace base
552