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