• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2013 The Flutter 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 "flutter/shell/platform/common/cpp/client_wrapper/testing/encodable_value_utils.h"
6 
7 #include <cmath>
8 
9 namespace flutter {
10 namespace testing {
11 
EncodableValuesAreEqual(const EncodableValue & a,const EncodableValue & b)12 bool EncodableValuesAreEqual(const EncodableValue& a, const EncodableValue& b) {
13   if (a.type() != b.type()) {
14     return false;
15   }
16 
17   switch (a.type()) {
18     case EncodableValue::Type::kNull:
19       return true;
20     case EncodableValue::Type::kBool:
21       return a.BoolValue() == b.BoolValue();
22     case EncodableValue::Type::kInt:
23       return a.IntValue() == b.IntValue();
24     case EncodableValue::Type::kLong:
25       return a.LongValue() == b.LongValue();
26     case EncodableValue::Type::kDouble:
27       // This is a crude epsilon, but fine for the values in the unit tests.
28       return std::abs(a.DoubleValue() - b.DoubleValue()) < 0.0001l;
29     case EncodableValue::Type::kString:
30       return a.StringValue() == b.StringValue();
31     case EncodableValue::Type::kByteList:
32       return a.ByteListValue() == b.ByteListValue();
33     case EncodableValue::Type::kIntList:
34       return a.IntListValue() == b.IntListValue();
35     case EncodableValue::Type::kLongList:
36       return a.LongListValue() == b.LongListValue();
37     case EncodableValue::Type::kDoubleList:
38       return a.DoubleListValue() == b.DoubleListValue();
39     case EncodableValue::Type::kList: {
40       const auto& a_list = a.ListValue();
41       const auto& b_list = b.ListValue();
42       if (a_list.size() != b_list.size()) {
43         return false;
44       }
45       for (size_t i = 0; i < a_list.size(); ++i) {
46         if (!EncodableValuesAreEqual(a_list[0], b_list[0])) {
47           return false;
48         }
49       }
50       return true;
51     }
52     case EncodableValue::Type::kMap: {
53       const auto& a_map = a.MapValue();
54       const auto& b_map = b.MapValue();
55       if (a_map.size() != b_map.size()) {
56         return false;
57       }
58       // Store references to all the keys in |b|.
59       std::vector<const EncodableValue*> unmatched_b_keys;
60       for (auto& pair : b_map) {
61         unmatched_b_keys.push_back(&pair.first);
62       }
63       // For each key,value in |a|, see if any of the not-yet-matched key,value
64       // pairs in |b| match by value; if so, remove that match and continue.
65       for (const auto& pair : a_map) {
66         bool found_match = false;
67         for (size_t i = 0; i < unmatched_b_keys.size(); ++i) {
68           const EncodableValue& b_key = *unmatched_b_keys[i];
69           if (EncodableValuesAreEqual(pair.first, b_key) &&
70               EncodableValuesAreEqual(pair.second, b_map.at(b_key))) {
71             found_match = true;
72             unmatched_b_keys.erase(unmatched_b_keys.begin() + i);
73             break;
74           }
75         }
76         if (!found_match) {
77           return false;
78         }
79       }
80       // If all entries had matches, consider the maps equal.
81       return true;
82     }
83   }
84   assert(false);
85   return false;
86 }
87 
88 }  // namespace testing
89 }  // namespace flutter
90