1 /* 2 * Copyright 2017-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. 3 */ 4 5 package kotlinx.serialization.json 6 7 import kotlinx.serialization.* 8 import kotlin.test.* 9 10 /** 11 * [https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER] 12 */ 13 internal const val MAX_SAFE_INTEGER: Double = 9007199254740991.toDouble() // 2^53 - 1 14 15 class DynamicToLongTest { 16 17 @Serializable 18 data class HasLong(val l: Long) 19 testnull20 private fun test(dynamic: dynamic, expectedResult: Result<Long>) { 21 val parsed = kotlin.runCatching { Json.decodeFromDynamic(HasLong.serializer(), dynamic).l } 22 assertEquals(expectedResult.isSuccess, parsed.isSuccess, "Results are different") 23 parsed.onSuccess { assertEquals(expectedResult.getOrThrow(), it) } 24 // to compare without message 25 parsed.onFailure { assertSame(expectedResult.exceptionOrNull()!!::class, it::class) } 26 } 27 shouldFailnull28 private fun shouldFail(dynamic: dynamic) = test(dynamic, Result.failure(SerializationException(""))) 29 30 @Test 31 fun canParseNotSoBigLongs() { 32 test(js("{l:1}"), Result.success(1)) 33 test(js("{l:0}"), Result.success(0)) 34 test(js("{l:-1}"), Result.success(-1)) 35 } 36 37 @Test ignoresIncorrectValuesnull38 fun ignoresIncorrectValues() { 39 shouldFail(js("{l:0.5}")) 40 shouldFail(js("{l: Math.PI}")) 41 shouldFail(js("{l: NaN}")) 42 shouldFail(js("""{l: "a string"}""")) 43 shouldFail(js("{l:Infinity}")) 44 shouldFail(js("{l:+Infinity}")) 45 shouldFail(js("{l:-Infinity}")) 46 } 47 48 @Test handlesEdgyValuesnull49 fun handlesEdgyValues() { 50 test(js("{l:Number.MAX_SAFE_INTEGER}"), Result.success(MAX_SAFE_INTEGER.toLong())) 51 test(js("{l:Number.MAX_SAFE_INTEGER - 1}"), Result.success(MAX_SAFE_INTEGER.toLong() - 1)) 52 test(js("{l:-Number.MAX_SAFE_INTEGER}"), Result.success(-MAX_SAFE_INTEGER.toLong())) 53 shouldFail(js("{l: Number.MAX_SAFE_INTEGER + 1}")) 54 shouldFail(js("{l: Number.MAX_SAFE_INTEGER + 2}")) 55 shouldFail(js("{l: -Number.MAX_SAFE_INTEGER - 1}")) 56 shouldFail(js("{l: 2e100}")) 57 shouldFail(js("{l: 2e100 + 1}")) 58 test(js("{l: Math.pow(2, 53) - 1}"), Result.success(MAX_SAFE_INTEGER.toLong())) 59 } 60 } 61