xref: /aosp_15_r20/external/fbjni/test/jni/iterator_tests.cpp (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1 /*
2  * Copyright (c) Facebook, Inc. and its affiliates.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <algorithm>
18 #include <unordered_map>
19 #include <unordered_set>
20 #include <vector>
21 
22 #include <fbjni/fbjni.h>
23 
24 #include "expect.h"
25 
26 using namespace facebook::jni;
27 
nativeTestListIterator(alias_ref<jclass>,alias_ref<JList<jstring>> jlist)28 jboolean nativeTestListIterator(
29     alias_ref<jclass>,
30     alias_ref<JList<jstring>> jlist) {
31   EXPECT(jlist);
32 
33   EXPECT(jlist->size() == 3);
34 
35   std::vector<std::string> vs1;
36   for (const auto& elem : *jlist) {
37     vs1.push_back(elem->toStdString());
38   }
39 
40   EXPECT(vs1.size() == 3);
41   EXPECT(vs1[0] == "red");
42   EXPECT(vs1[1] == "green");
43   EXPECT(vs1[2] == "blue");
44 
45   std::vector<std::string> vs2;
46   std::transform(
47       jlist->begin(),
48       jlist->end(),
49       std::back_inserter(vs2),
50       [](local_ref<jstring> elem) { return elem->toStdString(); });
51 
52   EXPECT(vs1 == vs2);
53 
54   std::vector<std::string> vs3 = {"red", "green", "blue"};
55 
56   EXPECT(vs1 == vs3);
57 
58   static auto iteratorMethod =
59       JIterable<jstring>::javaClassStatic()->getMethod<JIterator<jstring>()>(
60           "iterator");
61   auto iter = iteratorMethod(jlist);
62 
63   EXPECT(std::equal(iter->begin(), iter->end(), jlist->begin()));
64   EXPECT(std::equal(
65       iter->begin(),
66       iter->end(),
67       vs3.begin(),
68       [](const local_ref<jstring>& a, const std::string& b) {
69         return a->toStdString() == b;
70       }));
71 
72   return JNI_TRUE;
73 }
74 
nativeTestMapIterator(alias_ref<jclass>,alias_ref<JMap<jstring,JInteger>> jmap)75 jboolean nativeTestMapIterator(
76     alias_ref<jclass>,
77     alias_ref<JMap<jstring, JInteger>> jmap) {
78   EXPECT(jmap);
79 
80   EXPECT(jmap->size() == 3);
81 
82   std::unordered_map<std::string, int> umap;
83 
84   for (const auto& entry : *jmap) {
85     umap[entry.first->toStdString()] = entry.second->intValue();
86   }
87 
88   EXPECT(umap.size() == 3);
89 
90   EXPECT(umap["one"] == 1);
91   EXPECT(umap["two"] == 2);
92   EXPECT(umap["four"] == 4);
93 
94   // For an empty map, any types will do; the cast will only happen on null
95   // pointers, which will always succeed.
96   typedef JHashMap<jclass, jthrowable> TestMap;
97 
98   static auto testmapCtor =
99       TestMap::javaClassStatic()->getConstructor<TestMap::javaobject()>();
100   auto emptyMap = TestMap::javaClassStatic()->newObject(testmapCtor);
101   EXPECT(emptyMap->size() == 0);
102 
103   JHashMap<jclass, jthrowable>::Iterator i1 = emptyMap->begin();
104   JHashMap<jclass, jthrowable>::Iterator i2 = emptyMap->end();
105 
106   EXPECT(i1 == i2);
107 
108   return JNI_TRUE;
109 }
110 
nativeTestIterateWrongType(alias_ref<jclass>,alias_ref<JMap<jstring,JInteger::javaobject>> jmap)111 jboolean nativeTestIterateWrongType(
112     alias_ref<jclass>,
113     alias_ref<JMap<jstring, JInteger::javaobject>> jmap) {
114   EXPECT(jmap);
115 
116   EXPECT(jmap->size() == 3);
117 
118   for (const auto& entry : *jmap) {
119     (void)entry;
120   }
121 
122   // The above should throw an exception.
123   EXPECT(false);
124 
125   return JNI_FALSE;
126 }
127 
nativeTestIterateNullKey(alias_ref<jclass>,alias_ref<JMap<jstring,JInteger>> jmap)128 jboolean nativeTestIterateNullKey(
129     alias_ref<jclass>,
130     alias_ref<JMap<jstring, JInteger>> jmap) {
131   EXPECT(jmap);
132 
133   EXPECT(jmap->size() == 3);
134 
135   std::unordered_map<std::string, int> umap;
136   std::unordered_set<int> nullValues;
137 
138   for (const auto& entry : *jmap) {
139     if (entry.first) {
140       umap[entry.first->toStdString()] = entry.second->intValue();
141     } else {
142       nullValues.insert(entry.second->intValue());
143     }
144   }
145 
146   EXPECT(umap.size() == 2);
147 
148   EXPECT(umap["one"] == 1);
149   EXPECT(umap["four"] == 4);
150 
151   EXPECT(nullValues.size() == 1);
152   EXPECT(*nullValues.begin() == -99);
153 
154   return JNI_TRUE;
155 }
156 
nativeTestLargeMapIteration(alias_ref<jclass>,alias_ref<JMap<jstring,jstring>> jmap)157 jboolean nativeTestLargeMapIteration(
158     alias_ref<jclass>,
159     alias_ref<JMap<jstring, jstring>> jmap) {
160   EXPECT(jmap);
161   EXPECT(jmap->size() == 3000);
162 
163   for (const auto& entry : *jmap) {
164     if (!entry.first) {
165       return JNI_FALSE;
166     }
167   }
168   return JNI_TRUE;
169 }
170 
RegisterIteratorTests()171 void RegisterIteratorTests() {
172   registerNatives(
173       "com/facebook/jni/IteratorTests",
174       {
175           makeNativeMethod("nativeTestListIterator", nativeTestListIterator),
176           makeNativeMethod("nativeTestMapIterator", nativeTestMapIterator),
177           makeNativeMethod(
178               "nativeTestIterateWrongType", nativeTestIterateWrongType),
179           makeNativeMethod(
180               "nativeTestIterateNullKey", nativeTestIterateNullKey),
181           makeNativeMethod(
182               "nativeTestLargeMapIteration", nativeTestLargeMapIteration),
183       });
184 }
185