1 /*
<lambda>null2  * Copyright 2021 Google Inc. All rights reserved.
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 package com.google.flatbuffers.kotlin
17 
18 import com.google.flatbuffers.kotlin.FlexBuffersBuilder.Companion.SHARE_NONE
19 import kotlin.random.Random
20 import kotlin.test.Test
21 import kotlin.test.assertEquals
22 
23 class FlexBuffersTest {
24   @Test
25   fun testWriteInt() {
26     val values = listOf(
27       Byte.MAX_VALUE.toLong() to 3,
28       Short.MAX_VALUE.toLong() to 4,
29       Int.MAX_VALUE.toLong() to 6,
30       Long.MAX_VALUE to 10
31     )
32     val builder = FlexBuffersBuilder()
33     values.forEach {
34       builder.clear()
35       builder.put(it.first)
36       val data = builder.finish()
37       val ref = getRoot(data)
38       // although we put a long, it is shrink to a byte
39       assertEquals(it.second, data.limit)
40       assertEquals(it.first, ref.toLong())
41     }
42   }
43 
44   @Test
45   fun testWriteUInt() {
46     val values = listOf(
47       UByte.MAX_VALUE.toULong() to 3,
48       UShort.MAX_VALUE.toULong() to 4,
49       UInt.MAX_VALUE.toULong() to 6,
50       ULong.MAX_VALUE to 10
51     )
52     val builder = FlexBuffersBuilder()
53     values.forEach {
54       builder.clear()
55       builder.put(it.first)
56       val data = builder.finish()
57       val ref = getRoot(data)
58       // although we put a long, it is shrink to a byte
59       assertEquals(it.second, data.limit)
60       assertEquals(it.first, ref.toULong())
61     }
62   }
63 
64   @Test
65   fun testWriteString() {
66     val text = "Ḧ̵̘́ȩ̵̐l̶̿͜l̶͚͝o̷̦̚ ̷̫̊w̴̤͊ö̸̞́r̴͎̾l̷͚̐d̶̰̍"
67     val builder = FlexBuffersBuilder()
68     builder.put(text)
69     val data = builder.finish()
70     val ref = getRoot(data)
71     assertEquals(text, ref.toString())
72   }
73 
74   @Test
75   fun testInt8Array() {
76     val ary = intArrayOf(1, 2, 3, 4)
77     val builder = FlexBuffersBuilder()
78     builder.put(intArrayOf(1, 2, 3, 4))
79     val data = builder.finish()
80     val ref = getRoot(data)
81     // although we put a long, it is shrink to a byte
82     assertEquals(8, data.limit)
83     assertArrayEquals(ary, ref.toIntArray())
84   }
85 
86   @Test
87   fun testShortArray() {
88     val builder = FlexBuffersBuilder(ArrayReadWriteBuffer(20))
89     val numbers = ShortArray(10) { it.toShort() }
90     builder.put(numbers)
91     val data = builder.finish()
92     val ref = getRoot(data)
93     assertArrayEquals(numbers, ref.toShortArray())
94   }
95 
96   @Test
97   fun testHugeArray() {
98     val builder = FlexBuffersBuilder()
99     val numbers = IntArray(1024) { it }
100     builder.put(numbers)
101     val data = builder.finish()
102     val ref = getRoot(data)
103     assertArrayEquals(numbers, ref.toIntArray())
104   }
105 
106   @Test
107   fun testFloatArray() {
108     val builder = FlexBuffersBuilder()
109     val numbers = FloatArray(1024) { it * 0.05f }
110     builder.put(numbers)
111     val data = builder.finish()
112     val ref = getRoot(data)
113     assertArrayEquals(numbers, ref.toFloatArray())
114   }
115 
116   @Test
117   fun testDoubleArray() {
118     val builder = FlexBuffersBuilder()
119     val numbers = DoubleArray(1024) { it * 0.0005 }
120     builder.put(numbers)
121     val data = builder.finish()
122     val ref = getRoot(data)
123     assertArrayEquals(numbers, ref.toDoubleArray())
124   }
125 
126   @Test
127   fun testLongArray() {
128     val ary: LongArray = longArrayOf(0, Short.MIN_VALUE.toLong(), Int.MAX_VALUE.toLong(), Long.MAX_VALUE)
129     val builder = FlexBuffersBuilder()
130     builder.put(ary)
131     val data = builder.finish()
132     val ref = getRoot(data)
133     // although we put a long, it is shrink to a byte
134     assertArrayEquals(ary, ref.toLongArray())
135   }
136 
137   @Test
138   fun testStringArray() {
139     val ary = Array(5) { "Hello world number: $it" }
140     val builder = FlexBuffersBuilder(ArrayReadWriteBuffer(20), SHARE_NONE)
141     builder.putVector {
142       ary.forEach { put(it) }
143     }
144     val data = builder.finish()
145     val vec = getRoot(data).toVector()
146     // although we put a long, it is shrink to a byte
147     assertEquals(5, vec.size)
148     val stringAry = vec.map { it.toString() }.toTypedArray()
149     // although we put a long, it is shrink to a byte
150     assertArrayEquals(ary, stringAry)
151   }
152 
153   @Test
154   fun testBlobArray() {
155     val ary = ByteArray(1000) { Random.nextInt().toByte() }
156     val builder = FlexBuffersBuilder()
157     builder.put(ary)
158     val data = builder.finish()
159     val blob = getRoot(data).toBlob()
160     // although we put a long, it is shrink to a byte
161     assertArrayEquals(ary, blob.toByteArray())
162     for (i in 0 until blob.size) {
163       assertEquals(ary[i], blob[i])
164     }
165   }
166 
167   @Test
168   fun testArrays() {
169     val builder = FlexBuffersBuilder()
170     val ary: Array<String> = Array(5) { "Hello world number: $it" }
171     val numbers = IntArray(10) { it }
172     val doubles = DoubleArray(10) { it * 0.35 }
173 
174     // add 3 level array of arrays in the following way
175     // [ [ "..", ...] [ "..", ..., [ "..", ...] ] ]
176     val vec = builder.startVector()
177 
178     // [0, 1, 2, 3 ,4 ,5 ,6 ,7 ,8, 9]
179     val vec1 = builder.startVector()
180     numbers.forEach { builder.put(it) }
181     builder.endTypedVector(vec1)
182 
183     // [0, 2, 4, 6 , 8, 10, 12, 14, 16, 18]
184     builder.putTypedVector { doubles.forEach { put(it) } }
185 
186     // nested array
187     // [ "He..", "He..", "He..", "He..", "He..", [ "He..", "He..", "He..", "He..", "He.." ] ]
188     val vec3 = builder.startVector()
189     ary.forEach { builder.put(it) }
190     builder.putVector { ary.forEach { put("inner: $it") } }
191     builder.endVector(vec3)
192 
193     builder.endVector(vec)
194 
195     val data = builder.finish()
196     val ref = getRoot(data)
197     val vecRef = getRoot(data).toVector()
198     // although we put a long, it is shrink to a byte
199     assertEquals(3, vecRef.size)
200 
201     assertArrayEquals(numbers, vecRef[0].toVector().map { it.toInt() }.toIntArray())
202     assertArrayEquals(doubles, ref[1].toDoubleArray())
203     assertEquals("Hello world number: 4", vecRef[2][4].toString())
204     assertEquals("inner: Hello world number: 4", vecRef[2][5][4].toString())
205     assertEquals("inner: Hello world number: 4", ref[2][5][4].toString())
206   }
207 
208   @Test
209   fun testMap() {
210     val builder = FlexBuffersBuilder(shareFlag = FlexBuffersBuilder.SHARE_KEYS_AND_STRINGS)
211     builder.putVector {
212       put(10)
213       putMap {
214         this["chello"] = "world"
215         this["aint"] = 10
216         this["bfloat"] = 12.3
217       }
218       put("aString")
219     }
220 
221     val ref = getRoot(builder.finish())
222     val map = ref.toVector()
223     assertEquals(3, map.size)
224     assertEquals(10, map[0].toInt())
225     assertEquals("aString", map[2].toString())
226     assertEquals("world", map[1]["chello"].toString())
227     assertEquals(10, map[1]["aint"].toInt())
228     assertEquals(12.3, map[1]["bfloat"].toDouble())
229   }
230 
231   @Test
232   fun testMultiMap() {
233     val builder = FlexBuffersBuilder(shareFlag = FlexBuffersBuilder.SHARE_KEYS_AND_STRINGS)
234     builder.putMap {
235       this["hello"] = "world"
236       this["int"] = 10
237       this["float"] = 12.3
238       this["intarray"] = intArrayOf(1, 2, 3, 4, 5)
239       this.putMap("myMap") {
240         this["cool"] = "beans"
241       }
242     }
243 
244     val ref = getRoot(builder.finish())
245     val map = ref.toMap()
246     assertEquals(5, map.size)
247     assertEquals("world", map["hello"].toString())
248     assertEquals(10, map["int"].toInt())
249     assertEquals(12.3, map["float"].toDouble())
250     assertArrayEquals(intArrayOf(1, 2, 3, 4, 5), map["intarray"].toIntArray())
251     assertEquals("beans", ref["myMap"]["cool"].toString())
252     assertEquals(true, "myMap" in map)
253     assertEquals(true, "cool" in map["myMap"].toMap())
254 
255     // testing null values
256     assertEquals(true, ref["invalid_key"].isNull)
257 
258     val keys = map.keys.toTypedArray()
259     arrayOf("hello", "int", "float", "intarray", "myMap").sortedArray().forEachIndexed { i: Int, it: String ->
260       assertEquals(it, keys[i].toString())
261     }
262   }
263 
264   @Test
265   fun testBigStringMap() {
266     val builder = FlexBuffersBuilder(shareFlag = FlexBuffersBuilder.SHARE_KEYS_AND_STRINGS)
267 
268     val stringKey = Array(10000) { "Ḧ̵̘́ȩ̵̐myFairlyBigKey$it" }
269     val stringValue = Array(10000) { "Ḧ̵̘́ȩ̵̐myFairlyBigValue$it" }
270     val hashMap = mutableMapOf<String, String>()
271     val pos = builder.startMap()
272     for (i in stringKey.indices) {
273       builder[stringKey[i]] = stringValue[i]
274       hashMap[stringKey[i]] = stringValue[i]
275     }
276     builder.endMap(pos)
277     val ref = getRoot(builder.finish())
278     val map = ref.toMap()
279     val sortedKeys = stringKey.sortedArray()
280     val size = map.size
281     for (i in 0 until size) {
282       assertEquals(sortedKeys[i], map.keyAsString(i))
283       assertEquals(sortedKeys[i], map.keyAt(i).toString())
284       assertEquals(hashMap[sortedKeys[i]], map[map.keyAt(i)].toString())
285     }
286   }
287 
288   @Test
289   fun testKeysAccess() {
290     for (i in 1 until 1000) {
291       val utf8String = "ሰማይ አይታረስ ንጉሥ አይከሰስ።$i"
292       val bytes = ByteArray(Utf8.encodedLength(utf8String))
293       val pos = Utf8.encodeUtf8Array(utf8String, bytes)
294       val key = Key(ArrayReadWriteBuffer(bytes), 0, pos)
295       assertEquals(utf8String.length, key.sizeInChars)
296       for (j in utf8String.indices) {
297         assertEquals(utf8String[j], key[j])
298       }
299     }
300   }
301 }
302