1 /* 2 * Copyright 2024 The Android Open Source Project 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 package androidx.navigation.serialization 18 19 import android.os.Bundle 20 import android.os.Parcel 21 import android.os.Parcelable 22 import androidx.navigation.CollectionNavType 23 import androidx.navigation.NamedNavArgument 24 import androidx.navigation.NavArgument 25 import androidx.navigation.NavType 26 import androidx.navigation.navArgument 27 import com.google.common.truth.Truth.assertThat 28 import kotlin.reflect.typeOf 29 import kotlin.test.assertFailsWith 30 import kotlin.test.fail 31 import kotlinx.serialization.SerialName 32 import kotlinx.serialization.Serializable 33 import kotlinx.serialization.SerializationException 34 import kotlinx.serialization.serializer 35 import org.junit.Test 36 import org.junit.runner.RunWith 37 import org.junit.runners.JUnit4 38 39 @RunWith(JUnit4::class) 40 class NavArgumentGeneratorTest { 41 @Test convertToIntnull42 fun convertToInt() { 43 @Serializable class TestClass(val arg: Int) 44 45 val converted = serializer<TestClass>().generateNavArguments() 46 val expected = 47 navArgument("arg") { 48 type = NavType.IntType 49 nullable = false 50 } 51 assertThat(converted).containsExactlyInOrder(expected) 52 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 53 } 54 55 @Test convertToIntNullablenull56 fun convertToIntNullable() { 57 @Serializable class TestClass(val arg: Int?) 58 59 val converted = serializer<TestClass>().generateNavArguments() 60 val expected = 61 navArgument("arg") { 62 type = InternalNavType.IntNullableType 63 nullable = true 64 } 65 assertThat(converted).containsExactlyInOrder(expected) 66 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 67 } 68 69 @Test convertToStringnull70 fun convertToString() { 71 @Serializable class TestClass(val arg: String) 72 73 val converted = serializer<TestClass>().generateNavArguments() 74 val expected = 75 navArgument("arg") { 76 type = InternalNavType.StringNonNullableType 77 nullable = false 78 } 79 assertThat(converted).containsExactlyInOrder(expected) 80 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 81 } 82 83 @Test convertToStringNullablenull84 fun convertToStringNullable() { 85 @Serializable class TestClass(val arg: String?) 86 87 val converted = serializer<TestClass>().generateNavArguments() 88 val expected = 89 navArgument("arg") { 90 type = NavType.StringType 91 nullable = true 92 } 93 assertThat(converted).containsExactlyInOrder(expected) 94 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 95 } 96 97 @Test convertToBooleannull98 fun convertToBoolean() { 99 @Serializable class TestClass(val arg: Boolean) 100 101 val converted = serializer<TestClass>().generateNavArguments() 102 val expected = 103 navArgument("arg") { 104 type = NavType.BoolType 105 nullable = false 106 } 107 assertThat(converted).containsExactlyInOrder(expected) 108 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 109 } 110 111 @Test convertToBooleanNullablenull112 fun convertToBooleanNullable() { 113 @Serializable class TestClass(val arg: Boolean?) 114 115 val converted = serializer<TestClass>().generateNavArguments() 116 val expected = 117 navArgument("arg") { 118 type = InternalNavType.BoolNullableType 119 nullable = true 120 } 121 assertThat(converted).containsExactlyInOrder(expected) 122 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 123 } 124 125 @Test convertToDoublenull126 fun convertToDouble() { 127 @Serializable class TestClass(val arg: Double) 128 129 val converted = serializer<TestClass>().generateNavArguments() 130 val expected = 131 navArgument("arg") { 132 type = InternalNavType.DoubleType 133 nullable = false 134 } 135 assertThat(converted).containsExactlyInOrder(expected) 136 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 137 } 138 139 @Test convertToDoubleNullablenull140 fun convertToDoubleNullable() { 141 @Serializable class TestClass(val arg: Double?) 142 143 val converted = serializer<TestClass>().generateNavArguments() 144 val expected = 145 navArgument("arg") { 146 type = InternalNavType.DoubleNullableType 147 nullable = true 148 } 149 assertThat(converted).containsExactlyInOrder(expected) 150 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 151 } 152 153 @Test convertToFloatnull154 fun convertToFloat() { 155 @Serializable class TestClass(val arg: Float) 156 157 val converted = serializer<TestClass>().generateNavArguments() 158 val expected = 159 navArgument("arg") { 160 type = NavType.FloatType 161 nullable = false 162 } 163 assertThat(converted).containsExactlyInOrder(expected) 164 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 165 } 166 167 @Test convertToFloatNullablenull168 fun convertToFloatNullable() { 169 @Serializable class TestClass(val arg: Float?) 170 171 val converted = serializer<TestClass>().generateNavArguments() 172 val expected = 173 navArgument("arg") { 174 type = InternalNavType.FloatNullableType 175 nullable = true 176 } 177 assertThat(converted).containsExactlyInOrder(expected) 178 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 179 } 180 181 @Test convertToLongnull182 fun convertToLong() { 183 @Serializable class TestClass(val arg: Long) 184 185 val converted = serializer<TestClass>().generateNavArguments() 186 val expected = 187 navArgument("arg") { 188 type = NavType.LongType 189 nullable = false 190 } 191 assertThat(converted).containsExactlyInOrder(expected) 192 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 193 } 194 195 @Test convertToLongNullablenull196 fun convertToLongNullable() { 197 @Serializable class TestClass(val arg: Long?) 198 199 val converted = serializer<TestClass>().generateNavArguments() 200 val expected = 201 navArgument("arg") { 202 type = InternalNavType.LongNullableType 203 nullable = true 204 } 205 assertThat(converted).containsExactlyInOrder(expected) 206 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 207 } 208 209 @Test convertToIntArraynull210 fun convertToIntArray() { 211 @Serializable class TestClass(val arg: IntArray) 212 213 val converted = serializer<TestClass>().generateNavArguments() 214 val expected = 215 navArgument("arg") { 216 type = NavType.IntArrayType 217 nullable = false 218 } 219 assertThat(converted).containsExactlyInOrder(expected) 220 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 221 } 222 223 @Test convertToIntArrayNullablenull224 fun convertToIntArrayNullable() { 225 @Serializable class TestClass(val arg: IntArray?) 226 227 val converted = serializer<TestClass>().generateNavArguments() 228 val expected = 229 navArgument("arg") { 230 type = NavType.IntArrayType 231 nullable = true 232 } 233 assertThat(converted).containsExactlyInOrder(expected) 234 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 235 } 236 237 @Test convertToIntListnull238 fun convertToIntList() { 239 @Serializable class TestClass(val arg: List<Int>) 240 241 val converted = serializer<TestClass>().generateNavArguments() 242 val expected = 243 navArgument("arg") { 244 type = NavType.IntListType 245 nullable = false 246 } 247 assertThat(converted).containsExactlyInOrder(expected) 248 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 249 } 250 251 @Test convertArrayListToIntListnull252 fun convertArrayListToIntList() { 253 @Serializable class TestClass(val arg: ArrayList<Int>) 254 255 val converted = serializer<TestClass>().generateNavArguments() 256 val expected = 257 navArgument("arg") { 258 type = NavType.IntListType 259 nullable = false 260 } 261 assertThat(converted).containsExactlyInOrder(expected) 262 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 263 } 264 265 @Test convertToIntListNullablenull266 fun convertToIntListNullable() { 267 @Serializable class TestClass(val arg: List<Int>?) 268 269 val converted = serializer<TestClass>().generateNavArguments() 270 val expected = 271 navArgument("arg") { 272 type = NavType.IntListType 273 nullable = true 274 } 275 assertThat(converted).containsExactlyInOrder(expected) 276 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 277 } 278 279 @Test convertToLongArraynull280 fun convertToLongArray() { 281 @Serializable class TestClass(val arg: LongArray) 282 283 val converted = serializer<TestClass>().generateNavArguments() 284 val expected = 285 navArgument("arg") { 286 type = NavType.LongArrayType 287 nullable = false 288 } 289 assertThat(converted).containsExactlyInOrder(expected) 290 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 291 } 292 293 @Test convertToLongArrayNullablenull294 fun convertToLongArrayNullable() { 295 @Serializable class TestClass(val arg: LongArray?) 296 297 val converted = serializer<TestClass>().generateNavArguments() 298 val expected = 299 navArgument("arg") { 300 type = NavType.LongArrayType 301 nullable = true 302 } 303 assertThat(converted).containsExactlyInOrder(expected) 304 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 305 } 306 307 @Test convertToLongListnull308 fun convertToLongList() { 309 @Serializable class TestClass(val arg: List<Long>) 310 311 val converted = serializer<TestClass>().generateNavArguments() 312 val expected = 313 navArgument("arg") { 314 type = NavType.LongListType 315 nullable = false 316 } 317 assertThat(converted).containsExactlyInOrder(expected) 318 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 319 } 320 321 @Test convertArrayListToLongListnull322 fun convertArrayListToLongList() { 323 @Serializable class TestClass(val arg: ArrayList<Long>) 324 325 val converted = serializer<TestClass>().generateNavArguments() 326 val expected = 327 navArgument("arg") { 328 type = NavType.LongListType 329 nullable = false 330 } 331 assertThat(converted).containsExactlyInOrder(expected) 332 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 333 } 334 335 @Test convertToLongListNullablenull336 fun convertToLongListNullable() { 337 @Serializable class TestClass(val arg: List<Long>?) 338 339 val converted = serializer<TestClass>().generateNavArguments() 340 val expected = 341 navArgument("arg") { 342 type = NavType.LongListType 343 nullable = true 344 } 345 assertThat(converted).containsExactlyInOrder(expected) 346 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 347 } 348 349 @Test convertToFloatArraynull350 fun convertToFloatArray() { 351 @Serializable class TestClass(val arg: FloatArray) 352 353 val converted = serializer<TestClass>().generateNavArguments() 354 val expected = 355 navArgument("arg") { 356 type = NavType.FloatArrayType 357 nullable = false 358 } 359 assertThat(converted).containsExactlyInOrder(expected) 360 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 361 } 362 363 @Test convertToFloatArrayNullablenull364 fun convertToFloatArrayNullable() { 365 @Serializable class TestClass(val arg: FloatArray?) 366 367 val converted = serializer<TestClass>().generateNavArguments() 368 val expected = 369 navArgument("arg") { 370 type = NavType.FloatArrayType 371 nullable = true 372 } 373 assertThat(converted).containsExactlyInOrder(expected) 374 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 375 } 376 377 @Test convertToFloatListnull378 fun convertToFloatList() { 379 @Serializable class TestClass(val arg: List<Float>) 380 381 val converted = serializer<TestClass>().generateNavArguments() 382 val expected = 383 navArgument("arg") { 384 type = NavType.FloatListType 385 nullable = false 386 } 387 assertThat(converted).containsExactlyInOrder(expected) 388 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 389 } 390 391 @Test convertArrayListToFloatListnull392 fun convertArrayListToFloatList() { 393 @Serializable class TestClass(val arg: ArrayList<Float>) 394 395 val converted = serializer<TestClass>().generateNavArguments() 396 val expected = 397 navArgument("arg") { 398 type = NavType.FloatListType 399 nullable = false 400 } 401 assertThat(converted).containsExactlyInOrder(expected) 402 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 403 } 404 405 @Test convertToFloatListNullablenull406 fun convertToFloatListNullable() { 407 @Serializable class TestClass(val arg: List<Float>?) 408 409 val converted = serializer<TestClass>().generateNavArguments() 410 val expected = 411 navArgument("arg") { 412 type = NavType.FloatListType 413 nullable = true 414 } 415 assertThat(converted).containsExactlyInOrder(expected) 416 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 417 } 418 419 @Test convertToBoolArraynull420 fun convertToBoolArray() { 421 @Serializable class TestClass(val arg: BooleanArray) 422 423 val converted = serializer<TestClass>().generateNavArguments() 424 val expected = 425 navArgument("arg") { 426 type = NavType.BoolArrayType 427 nullable = false 428 } 429 assertThat(converted).containsExactlyInOrder(expected) 430 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 431 } 432 433 @Test convertToBoolArrayNullablenull434 fun convertToBoolArrayNullable() { 435 @Serializable class TestClass(val arg: BooleanArray?) 436 437 val converted = serializer<TestClass>().generateNavArguments() 438 val expected = 439 navArgument("arg") { 440 type = NavType.BoolArrayType 441 nullable = true 442 } 443 assertThat(converted).containsExactlyInOrder(expected) 444 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 445 } 446 447 @Test convertToBooleanListnull448 fun convertToBooleanList() { 449 @Serializable class TestClass(val arg: List<Boolean>) 450 451 val converted = serializer<TestClass>().generateNavArguments() 452 val expected = 453 navArgument("arg") { 454 type = NavType.BoolListType 455 nullable = false 456 } 457 assertThat(converted).containsExactlyInOrder(expected) 458 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 459 } 460 461 @Test convertArrayListToBooleanListnull462 fun convertArrayListToBooleanList() { 463 @Serializable class TestClass(val arg: ArrayList<Boolean>) 464 465 val converted = serializer<TestClass>().generateNavArguments() 466 val expected = 467 navArgument("arg") { 468 type = NavType.BoolListType 469 nullable = false 470 } 471 assertThat(converted).containsExactlyInOrder(expected) 472 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 473 } 474 475 @Test convertToBooleanListNullablenull476 fun convertToBooleanListNullable() { 477 @Serializable class TestClass(val arg: List<Boolean>?) 478 479 val converted = serializer<TestClass>().generateNavArguments() 480 val expected = 481 navArgument("arg") { 482 type = NavType.BoolListType 483 nullable = true 484 } 485 assertThat(converted).containsExactlyInOrder(expected) 486 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 487 } 488 489 @Test convertToDoubleArraynull490 fun convertToDoubleArray() { 491 @Serializable class TestClass(val arg: DoubleArray) 492 493 val converted = serializer<TestClass>().generateNavArguments() 494 val expected = 495 navArgument("arg") { 496 type = InternalNavType.DoubleArrayType 497 nullable = false 498 } 499 assertThat(converted).containsExactlyInOrder(expected) 500 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 501 } 502 503 @Test convertToDoubleArrayNullablenull504 fun convertToDoubleArrayNullable() { 505 @Serializable class TestClass(val arg: DoubleArray?) 506 507 val converted = serializer<TestClass>().generateNavArguments() 508 val expected = 509 navArgument("arg") { 510 type = InternalNavType.DoubleArrayType 511 nullable = true 512 } 513 assertThat(converted).containsExactlyInOrder(expected) 514 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 515 } 516 517 @Test convertToDoubleListnull518 fun convertToDoubleList() { 519 @Serializable class TestClass(val arg: List<Double>) 520 521 val converted = serializer<TestClass>().generateNavArguments() 522 val expected = 523 navArgument("arg") { 524 type = InternalNavType.DoubleListType 525 nullable = false 526 } 527 assertThat(converted).containsExactlyInOrder(expected) 528 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 529 } 530 531 @Test convertToDoubleListNullablenull532 fun convertToDoubleListNullable() { 533 @Serializable class TestClass(val arg: List<Double>?) 534 535 val converted = serializer<TestClass>().generateNavArguments() 536 val expected = 537 navArgument("arg") { 538 type = InternalNavType.DoubleListType 539 nullable = true 540 } 541 assertThat(converted).containsExactlyInOrder(expected) 542 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 543 } 544 545 @Test convertToStringArraynull546 fun convertToStringArray() { 547 @Serializable class TestClass(val arg: Array<String>) 548 549 val converted = serializer<TestClass>().generateNavArguments() 550 val expected = 551 navArgument("arg") { 552 type = NavType.StringArrayType 553 nullable = false 554 } 555 assertThat(converted).containsExactlyInOrder(expected) 556 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 557 } 558 559 @Test convertToStringArrayNullablenull560 fun convertToStringArrayNullable() { 561 @Serializable class TestClass(val arg: Array<String>?) 562 563 val converted = serializer<TestClass>().generateNavArguments() 564 val expected = 565 navArgument("arg") { 566 type = NavType.StringArrayType 567 nullable = true 568 } 569 assertThat(converted).containsExactlyInOrder(expected) 570 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 571 } 572 573 @Test convertToStringNullableArrayNullablenull574 fun convertToStringNullableArrayNullable() { 575 @Serializable class TestClass(val arg: Array<String?>?) 576 577 val converted = serializer<TestClass>().generateNavArguments() 578 val expected = 579 navArgument("arg") { 580 type = InternalNavType.StringNullableArrayType 581 nullable = true 582 } 583 assertThat(converted).containsExactlyInOrder(expected) 584 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 585 } 586 587 @Test convertToStringListnull588 fun convertToStringList() { 589 @Serializable class TestClass(val arg: List<String>) 590 591 val converted = serializer<TestClass>().generateNavArguments() 592 val expected = 593 navArgument("arg") { 594 type = NavType.StringListType 595 nullable = false 596 } 597 assertThat(converted).containsExactlyInOrder(expected) 598 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 599 } 600 601 @Test convertToStringListNullablenull602 fun convertToStringListNullable() { 603 @Serializable class TestClass(val arg: List<String>?) 604 605 val converted = serializer<TestClass>().generateNavArguments() 606 val expected = 607 navArgument("arg") { 608 type = NavType.StringListType 609 nullable = true 610 } 611 assertThat(converted).containsExactlyInOrder(expected) 612 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 613 } 614 615 @Test convertToStringNullableListnull616 fun convertToStringNullableList() { 617 @Serializable class TestClass(val arg: List<String?>) 618 val converted = serializer<TestClass>().generateNavArguments() 619 val expected = 620 navArgument("arg") { 621 type = InternalNavType.StringNullableListType 622 nullable = false 623 } 624 assertThat(converted).containsExactlyInOrder(expected) 625 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 626 } 627 628 @Test convertToStringNullableListNullablenull629 fun convertToStringNullableListNullable() { 630 @Serializable class TestClass(val arg: List<String?>?) 631 val converted = serializer<TestClass>().generateNavArguments() 632 val expected = 633 navArgument("arg") { 634 type = InternalNavType.StringNullableListType 635 nullable = true 636 } 637 assertThat(converted).containsExactlyInOrder(expected) 638 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 639 } 640 641 @Test convertArrayListToStringListnull642 fun convertArrayListToStringList() { 643 @Serializable class TestClass(val arg: ArrayList<String>) 644 645 val converted = serializer<TestClass>().generateNavArguments() 646 val expected = 647 navArgument("arg") { 648 type = NavType.StringListType 649 nullable = false 650 } 651 assertThat(converted).containsExactlyInOrder(expected) 652 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 653 } 654 655 @Test convertToEnumListnull656 fun convertToEnumList() { 657 @Serializable class TestClass(val arg: List<TestEnum>) 658 659 val converted = serializer<TestClass>().generateNavArguments() 660 val expected = 661 navArgument("arg") { 662 type = InternalAndroidNavType.EnumListType(TestEnum::class.java) 663 nullable = false 664 } 665 assertThat(converted).containsExactlyInOrder(expected) 666 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 667 } 668 669 @Test convertToEnumListNullablenull670 fun convertToEnumListNullable() { 671 @Serializable class TestClass(val arg: List<TestEnum>?) 672 673 val converted = serializer<TestClass>().generateNavArguments() 674 val expected = 675 navArgument("arg") { 676 type = InternalAndroidNavType.EnumListType(TestEnum::class.java) 677 nullable = true 678 } 679 assertThat(converted).containsExactlyInOrder(expected) 680 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 681 } 682 683 @Test convertToParcelablenull684 fun convertToParcelable() { 685 @Serializable 686 class TestParcelable : Parcelable { 687 override fun describeContents() = 0 688 689 override fun writeToParcel(dest: Parcel, flags: Int) {} 690 } 691 692 @Serializable class TestClass(val arg: TestParcelable) 693 694 val navType = 695 object : NavType<TestParcelable>(false) { 696 override fun put(bundle: Bundle, key: String, value: TestParcelable) {} 697 698 override fun get(bundle: Bundle, key: String) = null 699 700 override fun parseValue(value: String) = TestParcelable() 701 } 702 703 val converted = 704 serializer<TestClass>().generateNavArguments(mapOf(typeOf<TestParcelable>() to navType)) 705 val expected = 706 navArgument("arg") { 707 type = navType 708 nullable = false 709 } 710 assertThat(converted).containsExactlyInOrder(expected) 711 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 712 } 713 714 @Test convertToParcelableNullablenull715 fun convertToParcelableNullable() { 716 @Serializable 717 class TestParcelable : Parcelable { 718 override fun describeContents() = 0 719 720 override fun writeToParcel(dest: Parcel, flags: Int) {} 721 } 722 723 @Serializable class TestClass(val arg: TestParcelable?) 724 725 val navType = 726 object : NavType<TestParcelable?>(true) { 727 override fun put(bundle: Bundle, key: String, value: TestParcelable?) {} 728 729 override fun get(bundle: Bundle, key: String) = null 730 731 override fun parseValue(value: String) = TestParcelable() 732 } 733 734 val converted = 735 serializer<TestClass>() 736 .generateNavArguments(mapOf(typeOf<TestParcelable?>() to navType)) 737 val expected = 738 navArgument("arg") { 739 type = navType 740 nullable = true 741 } 742 assertThat(converted).containsExactlyInOrder(expected) 743 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 744 } 745 746 @Test convertToParcelableArraynull747 fun convertToParcelableArray() { 748 @Serializable 749 class TestParcelable : Parcelable { 750 override fun describeContents() = 0 751 752 override fun writeToParcel(dest: Parcel, flags: Int) {} 753 } 754 755 @Serializable class TestClass(val arg: Array<TestParcelable>) 756 757 val navType = 758 object : NavType<Array<TestParcelable>>(false) { 759 override fun put(bundle: Bundle, key: String, value: Array<TestParcelable>) {} 760 761 override fun get(bundle: Bundle, key: String) = null 762 763 override fun parseValue(value: String) = emptyArray<TestParcelable>() 764 } 765 val converted = 766 serializer<TestClass>() 767 .generateNavArguments(mapOf(typeOf<Array<TestParcelable>>() to navType)) 768 val expected = 769 navArgument("arg") { 770 type = navType 771 nullable = false 772 } 773 assertThat(converted).containsExactlyInOrder(expected) 774 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 775 } 776 777 @Test convertToParcelableArrayNullablenull778 fun convertToParcelableArrayNullable() { 779 @Serializable 780 class TestParcelable : Parcelable { 781 override fun describeContents() = 0 782 783 override fun writeToParcel(dest: Parcel, flags: Int) {} 784 } 785 786 @Serializable class TestClass(val arg: Array<TestParcelable>?) 787 788 val navType = 789 object : NavType<Array<TestParcelable>>(true) { 790 override fun put(bundle: Bundle, key: String, value: Array<TestParcelable>) {} 791 792 override fun get(bundle: Bundle, key: String) = null 793 794 override fun parseValue(value: String) = emptyArray<TestParcelable>() 795 } 796 val converted = 797 serializer<TestClass>() 798 .generateNavArguments(mapOf(typeOf<Array<TestParcelable>?>() to navType)) 799 val expected = 800 navArgument("arg") { 801 type = navType 802 nullable = true 803 } 804 assertThat(converted).containsExactlyInOrder(expected) 805 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 806 } 807 808 @Test convertToSerializablenull809 fun convertToSerializable() { 810 @Serializable class TestSerializable : java.io.Serializable 811 812 @Serializable class TestClass(val arg: TestSerializable) 813 814 val navType = 815 object : NavType<TestSerializable>(false) { 816 override fun put(bundle: Bundle, key: String, value: TestSerializable) {} 817 818 override fun get(bundle: Bundle, key: String) = null 819 820 override fun parseValue(value: String) = TestSerializable() 821 } 822 val converted = 823 serializer<TestClass>() 824 .generateNavArguments(mapOf(typeOf<TestSerializable>() to navType)) 825 val expected = 826 navArgument("arg") { 827 type = navType 828 nullable = false 829 } 830 assertThat(converted).containsExactlyInOrder(expected) 831 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 832 } 833 834 @Test convertToSerializableNullablenull835 fun convertToSerializableNullable() { 836 @Serializable class TestSerializable : java.io.Serializable 837 838 @Serializable class TestClass(val arg: TestSerializable?) 839 840 val navType = 841 object : NavType<TestSerializable>(true) { 842 override fun put(bundle: Bundle, key: String, value: TestSerializable) {} 843 844 override fun get(bundle: Bundle, key: String) = null 845 846 override fun parseValue(value: String) = TestSerializable() 847 } 848 val converted = 849 serializer<TestClass>() 850 .generateNavArguments(mapOf(typeOf<TestSerializable?>() to navType)) 851 val expected = 852 navArgument("arg") { 853 type = navType 854 nullable = true 855 } 856 assertThat(converted).containsExactlyInOrder(expected) 857 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 858 } 859 860 @Test convertToSerializableArraynull861 fun convertToSerializableArray() { 862 @Serializable class TestSerializable : java.io.Serializable 863 864 @Serializable class TestClass(val arg: Array<TestSerializable>) 865 866 val navType = 867 object : NavType<Array<TestSerializable>>(false) { 868 override fun put(bundle: Bundle, key: String, value: Array<TestSerializable>) {} 869 870 override fun get(bundle: Bundle, key: String) = null 871 872 override fun parseValue(value: String) = emptyArray<TestSerializable>() 873 } 874 val converted = 875 serializer<TestClass>() 876 .generateNavArguments(mapOf(typeOf<Array<TestSerializable>>() to navType)) 877 val expected = 878 navArgument("arg") { 879 type = navType 880 nullable = false 881 } 882 assertThat(converted).containsExactlyInOrder(expected) 883 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 884 } 885 886 @Test convertToSerializableArrayNullablenull887 fun convertToSerializableArrayNullable() { 888 @Serializable class TestSerializable : java.io.Serializable 889 890 @Serializable class TestClass(val arg: Array<TestSerializable>?) 891 892 val navType = 893 object : NavType<Array<TestSerializable>>(true) { 894 override fun put(bundle: Bundle, key: String, value: Array<TestSerializable>) {} 895 896 override fun get(bundle: Bundle, key: String) = null 897 898 override fun parseValue(value: String) = emptyArray<TestSerializable>() 899 } 900 val converted = 901 serializer<TestClass>() 902 .generateNavArguments(mapOf(typeOf<Array<TestSerializable>?>() to navType)) 903 val expected = 904 navArgument("arg") { 905 type = navType 906 nullable = true 907 } 908 assertThat(converted).containsExactlyInOrder(expected) 909 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 910 } 911 912 @Test convertToEnumnull913 fun convertToEnum() { 914 @Serializable class TestClass(val arg: TestEnum) 915 916 val expected = 917 navArgument("arg") { 918 type = NavType.EnumType(TestEnum::class.java) 919 nullable = false 920 } 921 val converted = serializer<TestClass>().generateNavArguments() 922 assertThat(converted).containsExactlyInOrder(expected) 923 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 924 } 925 926 @Test convertToTopLevelEnumnull927 fun convertToTopLevelEnum() { 928 @Serializable class TestClass(val arg: TestTopLevelEnum) 929 930 val expected = 931 navArgument("arg") { 932 type = NavType.EnumType(TestTopLevelEnum::class.java) 933 nullable = false 934 } 935 val converted = serializer<TestClass>().generateNavArguments() 936 assertThat(converted).containsExactlyInOrder(expected) 937 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 938 } 939 940 @Test convertToEnumNullablenull941 fun convertToEnumNullable() { 942 @Serializable class TestClass(val arg: TestEnum?) 943 944 @Suppress("UNCHECKED_CAST") 945 val expected = 946 navArgument("arg") { 947 type = 948 InternalAndroidNavType.EnumNullableType(TestEnum::class.java as Class<Enum<*>?>) 949 nullable = true 950 } 951 val converted = serializer<TestClass>().generateNavArguments() 952 assertThat(converted).containsExactlyInOrder(expected) 953 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 954 } 955 956 @Test convertToNestedEnumnull957 fun convertToNestedEnum() { 958 @Serializable class TestClass(val arg: EnumWrapper.NestedEnum) 959 960 val expected = 961 navArgument("arg") { 962 type = NavType.EnumType(EnumWrapper.NestedEnum::class.java) 963 nullable = false 964 } 965 val converted = serializer<TestClass>().generateNavArguments() 966 assertThat(converted).containsExactlyInOrder(expected) 967 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 968 } 969 970 @Test convertToEnumOverriddenSerialNameIllegalnull971 fun convertToEnumOverriddenSerialNameIllegal() { 972 @Serializable class TestClass(val arg: TestEnumCustomSerialName) 973 974 val exception = 975 assertFailsWith<IllegalArgumentException> { 976 serializer<TestClass>().generateNavArguments() 977 } 978 assertThat(exception.message) 979 .isEqualTo( 980 "Cannot find class with name \"MyCustomSerialName\". Ensure that the " + 981 "serialName for this argument is the default fully qualified name." + 982 "\nIf the build is minified, try annotating the Enum class " + 983 "with \"androidx.annotation.Keep\" to ensure the Enum is not removed." 984 ) 985 } 986 987 @Test convertToEnumArraynull988 fun convertToEnumArray() { 989 @Serializable class TestClass(val arg: Array<TestEnum>) 990 val navType = 991 object : CollectionNavType<Array<TestEnum>>(false) { 992 override fun put(bundle: Bundle, key: String, value: Array<TestEnum>) {} 993 994 override fun serializeAsValues(value: Array<TestEnum>) = emptyList<String>() 995 996 override fun emptyCollection(): Array<TestEnum> = emptyArray() 997 998 override fun get(bundle: Bundle, key: String) = null 999 1000 override fun parseValue(value: String) = emptyArray<TestEnum>() 1001 } 1002 val converted = 1003 serializer<TestClass>() 1004 .generateNavArguments(mapOf(typeOf<Array<TestEnum>>() to navType)) 1005 val expected = 1006 navArgument("arg") { 1007 type = navType 1008 nullable = false 1009 } 1010 assertThat(converted).containsExactlyInOrder(expected) 1011 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 1012 } 1013 1014 @Test convertValueClassnull1015 fun convertValueClass() { 1016 // test value class as destination route 1017 val converted = serializer<TestValueClass>().generateNavArguments() 1018 val expected = 1019 navArgument("arg") { 1020 type = NavType.IntType 1021 nullable = false 1022 unknownDefaultValuePresent = false 1023 } 1024 assertThat(converted).containsExactlyInOrder(expected) 1025 1026 // test value class as route arg 1027 @Serializable class TestClass(val arg: TestValueClass) 1028 val navType = 1029 object : NavType<TestValueClass>(false) { 1030 override fun put(bundle: Bundle, key: String, value: TestValueClass) {} 1031 1032 override fun get(bundle: Bundle, key: String): TestValueClass? = null 1033 1034 override fun parseValue(value: String): TestValueClass = TestValueClass(0) 1035 } 1036 val converted2 = 1037 serializer<TestClass>().generateNavArguments(mapOf(typeOf<TestValueClass>() to navType)) 1038 val expected2 = 1039 navArgument("arg") { 1040 type = navType 1041 nullable = false 1042 unknownDefaultValuePresent = false 1043 } 1044 assertThat(converted2).containsExactlyInOrder(expected2) 1045 } 1046 1047 @Test convertWithDefaultValuenull1048 fun convertWithDefaultValue() { 1049 @Serializable class TestClass(val arg: String = "test") 1050 val converted = serializer<TestClass>().generateNavArguments() 1051 val expected = 1052 navArgument("arg") { 1053 type = InternalNavType.StringNonNullableType 1054 nullable = false 1055 unknownDefaultValuePresent = true 1056 } 1057 assertThat(converted).containsExactlyInOrder(expected) 1058 assertThat(converted[0].argument.isDefaultValueUnknown).isTrue() 1059 } 1060 1061 @Test convertNullableWithDefaultValuenull1062 fun convertNullableWithDefaultValue() { 1063 @Serializable class TestClass(val arg: String? = "test") 1064 val converted = serializer<TestClass>().generateNavArguments() 1065 val expected = 1066 navArgument("arg") { 1067 type = NavType.StringType 1068 nullable = true 1069 unknownDefaultValuePresent = true 1070 // since String? is nullable, we cannot know for sure the default value is not null 1071 } 1072 assertThat(converted).containsExactlyInOrder(expected) 1073 assertThat(converted[0].argument.isDefaultValueUnknown).isTrue() 1074 } 1075 1076 @Test convertNullableWithNullDefaultValuenull1077 fun convertNullableWithNullDefaultValue() { 1078 @Serializable class TestClass(val arg: String? = null) 1079 val converted = serializer<TestClass>().generateNavArguments() 1080 val expected = 1081 navArgument("arg") { 1082 type = NavType.StringType 1083 nullable = true 1084 unknownDefaultValuePresent = true 1085 } 1086 assertThat(converted).containsExactlyInOrder(expected) 1087 assertThat(converted[0].argument.isDefaultValueUnknown).isTrue() 1088 } 1089 1090 @Test convertIllegalCustomTypenull1091 fun convertIllegalCustomType() { 1092 @Serializable class TestClass(val arg: Set<String>) 1093 1094 val exception = 1095 assertFailsWith<IllegalArgumentException> { 1096 serializer<TestClass>().generateNavArguments() 1097 } 1098 1099 assertThat(exception.message) 1100 .isEqualTo( 1101 "Route androidx.navigation.serialization.NavArgumentGeneratorTest" + 1102 ".convertIllegalCustomType.TestClass could not find any NavType for " + 1103 "argument arg of type kotlin.collections.LinkedHashSet - typeMap " + 1104 "received was {}" 1105 ) 1106 } 1107 1108 @Test convertCustomTypenull1109 fun convertCustomType() { 1110 @Serializable class TestClass(val arg: ArrayList<String>) 1111 1112 val CustomNavType = 1113 object : NavType<ArrayList<String>>(false) { 1114 override fun put(bundle: Bundle, key: String, value: ArrayList<String>) {} 1115 1116 override fun get(bundle: Bundle, key: String): ArrayList<String> = arrayListOf() 1117 1118 override fun parseValue(value: String): ArrayList<String> = arrayListOf() 1119 } 1120 1121 val converted = 1122 serializer<TestClass>() 1123 .generateNavArguments(mapOf(typeOf<ArrayList<String>>() to CustomNavType)) 1124 val expected = 1125 navArgument("arg") { 1126 type = CustomNavType 1127 nullable = false 1128 } 1129 assertThat(converted).containsExactlyInOrder(expected) 1130 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 1131 } 1132 1133 @Test convertCustomTypeNullablenull1134 fun convertCustomTypeNullable() { 1135 @Serializable class TestClass(val arg: ArrayList<String>?) 1136 1137 val CustomNavType = 1138 object : NavType<ArrayList<String>?>(true) { 1139 override fun put(bundle: Bundle, key: String, value: ArrayList<String>?) {} 1140 1141 override fun get(bundle: Bundle, key: String): ArrayList<String> = arrayListOf() 1142 1143 override fun parseValue(value: String): ArrayList<String> = arrayListOf() 1144 } 1145 1146 val converted = 1147 serializer<TestClass>() 1148 .generateNavArguments(mapOf(typeOf<ArrayList<String>?>() to CustomNavType)) 1149 val expected = 1150 navArgument("arg") { 1151 type = CustomNavType 1152 nullable = true 1153 } 1154 assertThat(converted).containsExactlyInOrder(expected) 1155 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 1156 } 1157 1158 @Test convertCustomTypeNullableIllegalnull1159 fun convertCustomTypeNullableIllegal() { 1160 val CustomNavType = 1161 object : NavType<ArrayList<String>>(false) { 1162 override val name = "customNavType" 1163 1164 override fun put(bundle: Bundle, key: String, value: ArrayList<String>) {} 1165 1166 override fun get(bundle: Bundle, key: String): ArrayList<String> = arrayListOf() 1167 1168 override fun parseValue(value: String): ArrayList<String> = arrayListOf() 1169 } 1170 1171 // CustomNavType does not allow nullable but we declare the arg as nullable here 1172 @Serializable class TestClass(val arg: ArrayList<String>?) 1173 1174 val exception = 1175 assertFailsWith<IllegalArgumentException> { 1176 serializer<TestClass>() 1177 .generateNavArguments(mapOf(typeOf<ArrayList<String>?>() to CustomNavType)) 1178 } 1179 assertThat(exception.message).isEqualTo("customNavType does not allow nullable values") 1180 } 1181 1182 @Test convertMultiplenull1183 fun convertMultiple() { 1184 @Serializable class TestClass(val arg: Int, val arg2: String?) 1185 1186 val converted = serializer<TestClass>().generateNavArguments() 1187 val expectedInt = 1188 navArgument("arg") { 1189 type = NavType.IntType 1190 nullable = false 1191 } 1192 val expectedString = 1193 navArgument("arg2") { 1194 type = NavType.StringType 1195 nullable = true 1196 } 1197 assertThat(converted).containsExactlyInOrder(expectedInt, expectedString) 1198 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 1199 assertThat(converted[1].argument.isDefaultValueUnknown).isFalse() 1200 } 1201 1202 @Test convertMultipleWithDefaultValuesnull1203 fun convertMultipleWithDefaultValues() { 1204 @Serializable class TestClass(val arg: Int = 0, val arg2: String? = "test") 1205 1206 val converted = serializer<TestClass>().generateNavArguments() 1207 val expectedInt = 1208 navArgument("arg") { 1209 type = NavType.IntType 1210 nullable = false 1211 unknownDefaultValuePresent = true 1212 } 1213 val expectedString = 1214 navArgument("arg2") { 1215 type = NavType.StringType 1216 nullable = true 1217 unknownDefaultValuePresent = true 1218 } 1219 assertThat(converted).containsExactlyInOrder(expectedInt, expectedString) 1220 assertThat(converted[0].argument.isDefaultValueUnknown).isTrue() 1221 assertThat(converted[1].argument.isDefaultValueUnknown).isTrue() 1222 } 1223 1224 @Test convertMultipleCustomTypesnull1225 fun convertMultipleCustomTypes() { 1226 @Serializable class TestClass(val arg: ArrayList<String>?, val arg2: ArrayList<Int>) 1227 1228 val CustomStringList = 1229 object : NavType<ArrayList<String>?>(true) { 1230 override fun put(bundle: Bundle, key: String, value: ArrayList<String>?) {} 1231 1232 override fun get(bundle: Bundle, key: String): ArrayList<String> = arrayListOf() 1233 1234 override fun parseValue(value: String): ArrayList<String> = arrayListOf() 1235 } 1236 1237 val CustomIntList = 1238 object : NavType<ArrayList<Int>>(true) { 1239 override fun put(bundle: Bundle, key: String, value: ArrayList<Int>) {} 1240 1241 override fun get(bundle: Bundle, key: String): ArrayList<Int> = arrayListOf() 1242 1243 override fun parseValue(value: String): ArrayList<Int> = arrayListOf() 1244 } 1245 1246 val converted = 1247 serializer<TestClass>() 1248 .generateNavArguments( 1249 mapOf( 1250 typeOf<ArrayList<String>?>() to CustomStringList, 1251 typeOf<ArrayList<Int>>() to CustomIntList 1252 ) 1253 ) 1254 val expectedStringList = 1255 navArgument("arg") { 1256 type = CustomStringList 1257 nullable = true 1258 } 1259 val expectedIntList = 1260 navArgument("arg2") { 1261 type = CustomIntList 1262 nullable = false 1263 } 1264 assertThat(converted).containsExactlyInOrder(expectedStringList, expectedIntList) 1265 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 1266 assertThat(converted[1].argument.isDefaultValueUnknown).isFalse() 1267 } 1268 1269 @Test convertMultipleCustomTypesWithDefaultValuenull1270 fun convertMultipleCustomTypesWithDefaultValue() { 1271 @Serializable 1272 class TestClass( 1273 val arg: ArrayList<String>? = arrayListOf(), 1274 val arg2: ArrayList<Int> = arrayListOf() 1275 ) 1276 1277 val CustomStringList = 1278 object : NavType<ArrayList<String>?>(true) { 1279 override fun put(bundle: Bundle, key: String, value: ArrayList<String>?) {} 1280 1281 override fun get(bundle: Bundle, key: String): ArrayList<String> = arrayListOf() 1282 1283 override fun parseValue(value: String): ArrayList<String> = arrayListOf() 1284 } 1285 1286 val CustomIntList = 1287 object : NavType<ArrayList<Int>>(true) { 1288 override fun put(bundle: Bundle, key: String, value: ArrayList<Int>) {} 1289 1290 override fun get(bundle: Bundle, key: String): ArrayList<Int> = arrayListOf() 1291 1292 override fun parseValue(value: String): ArrayList<Int> = arrayListOf() 1293 } 1294 1295 val converted = 1296 serializer<TestClass>() 1297 .generateNavArguments( 1298 mapOf( 1299 typeOf<ArrayList<String>?>() to CustomStringList, 1300 typeOf<ArrayList<Int>>() to CustomIntList 1301 ) 1302 ) 1303 val expectedStringList = 1304 navArgument("arg") { 1305 type = CustomStringList 1306 nullable = true 1307 unknownDefaultValuePresent = true 1308 } 1309 val expectedIntList = 1310 navArgument("arg2") { 1311 type = CustomIntList 1312 nullable = false 1313 unknownDefaultValuePresent = true 1314 } 1315 assertThat(converted).containsExactlyInOrder(expectedStringList, expectedIntList) 1316 assertThat(converted[0].argument.isDefaultValueUnknown).isTrue() 1317 assertThat(converted[1].argument.isDefaultValueUnknown).isTrue() 1318 } 1319 1320 @Test convertNestedCustomTypesnull1321 fun convertNestedCustomTypes() { 1322 @Serializable class TestClass(val arg: ArrayList<List<String>>) 1323 1324 val CustomStringList = 1325 object : NavType<ArrayList<List<String>>>(false) { 1326 override fun put(bundle: Bundle, key: String, value: ArrayList<List<String>>) {} 1327 1328 override fun get(bundle: Bundle, key: String): ArrayList<List<String>> = 1329 arrayListOf() 1330 1331 override fun parseValue(value: String): ArrayList<List<String>> = arrayListOf() 1332 } 1333 1334 val converted = 1335 serializer<TestClass>() 1336 .generateNavArguments(mapOf(typeOf<ArrayList<List<String>>>() to CustomStringList)) 1337 val expectedStringList = 1338 navArgument("arg") { 1339 type = CustomStringList 1340 nullable = false 1341 } 1342 assertThat(converted).containsExactlyInOrder(expectedStringList) 1343 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 1344 } 1345 1346 @Test convertNativeAndCustomTypesnull1347 fun convertNativeAndCustomTypes() { 1348 @Serializable class TestClass(val arg: String, val arg2: ArrayList<Int>) 1349 1350 val CustomIntList = 1351 object : NavType<ArrayList<Int>>(true) { 1352 override fun put(bundle: Bundle, key: String, value: ArrayList<Int>) {} 1353 1354 override fun get(bundle: Bundle, key: String): ArrayList<Int> = arrayListOf() 1355 1356 override fun parseValue(value: String): ArrayList<Int> = arrayListOf() 1357 } 1358 1359 val converted = 1360 serializer<TestClass>() 1361 .generateNavArguments(mapOf(typeOf<ArrayList<Int>>() to CustomIntList)) 1362 val expectedString = 1363 navArgument("arg") { 1364 type = InternalNavType.StringNonNullableType 1365 nullable = false 1366 } 1367 val expectedIntList = 1368 navArgument("arg2") { 1369 type = CustomIntList 1370 nullable = false 1371 } 1372 1373 assertThat(converted).containsExactlyInOrder(expectedString, expectedIntList) 1374 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 1375 assertThat(converted[1].argument.isDefaultValueUnknown).isFalse() 1376 } 1377 1378 @Test convertPrioritizesProvidedNavTypenull1379 fun convertPrioritizesProvidedNavType() { 1380 val CustomIntNavType = 1381 object : NavType<Int>(true) { 1382 override fun put(bundle: Bundle, key: String, value: Int) {} 1383 1384 override fun get(bundle: Bundle, key: String): Int = 0 1385 1386 override fun parseValue(value: String): Int = 0 1387 } 1388 1389 @Serializable class TestClass(val arg: Int) 1390 1391 val converted = 1392 serializer<TestClass>().generateNavArguments(mapOf(typeOf<Int>() to CustomIntNavType)) 1393 val expected = 1394 navArgument("arg") { 1395 type = CustomIntNavType 1396 nullable = false 1397 } 1398 assertThat(converted).containsExactlyInOrder(expected) 1399 assertThat(converted[0]).isNotEqualTo(NavType.IntType) 1400 assertThat(converted[0].argument.isDefaultValueUnknown).isFalse() 1401 } 1402 1403 @Test convertOnlyIfArgHasBackingFieldnull1404 fun convertOnlyIfArgHasBackingField() { 1405 @Serializable 1406 class TestClass { 1407 val noBackingField: Int 1408 get() = 0 1409 } 1410 1411 val converted = serializer<TestClass>().generateNavArguments() 1412 assertThat(converted).isEmpty() 1413 } 1414 1415 @Test convertArgFromClassBodynull1416 fun convertArgFromClassBody() { 1417 @Serializable 1418 class TestClass { 1419 val arg: Int = 0 1420 } 1421 1422 val converted = serializer<TestClass>().generateNavArguments() 1423 val expected = 1424 navArgument("arg") { 1425 type = NavType.IntType 1426 nullable = false 1427 unknownDefaultValuePresent = true 1428 } 1429 assertThat(converted).containsExactlyInOrder(expected) 1430 assertThat(converted[0].argument.isDefaultValueUnknown).isTrue() 1431 } 1432 1433 @Test nonSerializableClassInvalidnull1434 fun nonSerializableClassInvalid() { 1435 @SerialName(PATH_SERIAL_NAME) class TestClass 1436 1437 assertFailsWith<SerializationException> { 1438 // the class must be serializable 1439 serializer<TestClass>().generateNavArguments() 1440 } 1441 } 1442 1443 @Test abstractClassInvalidnull1444 fun abstractClassInvalid() { 1445 @Serializable abstract class TestClass(val arg: Int) 1446 1447 val serializer = serializer<TestClass>() 1448 val exception = 1449 assertFailsWith<IllegalArgumentException> { serializer.generateNavArguments() } 1450 assertThat(exception.message) 1451 .isEqualTo( 1452 "Cannot generate NavArguments for polymorphic serializer " + 1453 "kotlinx.serialization.PolymorphicSerializer(baseClass: " + 1454 "class androidx.navigation.serialization." + 1455 "NavArgumentGeneratorTest\$abstractClassInvalid\$TestClass (Kotlin reflection " + 1456 "is not available)). Arguments can only be generated from concrete classes " + 1457 "or objects." 1458 ) 1459 } 1460 1461 @Test childClassOfAbstract_duplicateArgsnull1462 fun childClassOfAbstract_duplicateArgs() { 1463 @Serializable abstract class TestAbstractClass(val arg: Int) 1464 1465 @Serializable class TestClass(val arg2: Int) : TestAbstractClass(0) 1466 1467 val serializer = serializer<TestClass>() 1468 val converted = serializer.generateNavArguments() 1469 // args will be duplicated 1470 val expectedInt = 1471 navArgument("arg") { 1472 type = NavType.IntType 1473 nullable = false 1474 } 1475 val expectedInt2 = 1476 navArgument("arg2") { 1477 type = NavType.IntType 1478 nullable = false 1479 } 1480 assertThat(converted).containsExactlyInOrder(expectedInt, expectedInt2) 1481 } 1482 1483 @Test childClassOfSealed_withArgsnull1484 fun childClassOfSealed_withArgs() { 1485 val serializer = serializer<SealedClass.TestClass>() 1486 val converted = serializer.generateNavArguments() 1487 // child class overrides parent variable so only child variables are generated as args 1488 val expected = 1489 navArgument("arg2") { 1490 type = NavType.IntType 1491 nullable = false 1492 } 1493 assertThat(converted).containsExactlyInOrder(expected) 1494 } 1495 1496 @Serializable @JvmInline value class TestValueClass(val arg: Int) 1497 1498 // writing our own assert so we don't need to override NamedNavArgument's equals 1499 // and hashcode which will need to be public api. assertThatnull1500 private fun assertThat(actual: List<NamedNavArgument>) = actual 1501 1502 private fun List<NamedNavArgument>.containsExactlyInOrder( 1503 vararg expectedArgs: NamedNavArgument 1504 ) { 1505 if (expectedArgs.size != this.size) { 1506 fail("expected list has size ${expectedArgs.size} and actual list has size $size}") 1507 } 1508 for (i in indices) { 1509 val actual = this[i] 1510 val expected = expectedArgs[i] 1511 if (expected.name != actual.name) { 1512 fail("expected name ${expected.name}, was actually ${actual.name}") 1513 } 1514 1515 if (!expected.argument.isEqual(actual.argument)) { 1516 fail( 1517 """expected ${expected.name} to be: 1518 | ${expected.argument} 1519 | but was: 1520 | ${actual.argument} 1521 """ 1522 .trimMargin() 1523 ) 1524 } 1525 } 1526 } 1527 NavArgumentnull1528 private fun NavArgument.isEqual(other: NavArgument): Boolean { 1529 if (this === other) return true 1530 if (javaClass != other.javaClass) return false 1531 if (isNullable != other.isNullable) return false 1532 if (isDefaultValuePresent != other.isDefaultValuePresent) return false 1533 if (isDefaultValueUnknown != other.isDefaultValueUnknown) return false 1534 if (type != other.type) return false 1535 // In context of serialization, we can only tell if defaultValue is present but don't know 1536 // actual value, so we cannot compare it to the generated defaultValue. But if 1537 // there is no defaultValue, we expect them both to be null. 1538 return if (!isDefaultValuePresent) { 1539 defaultValue == null && other.defaultValue == null 1540 } else true 1541 } 1542 1543 enum class TestEnum { 1544 TEST 1545 } 1546 1547 @SerialName("MyCustomSerialName") 1548 enum class TestEnumCustomSerialName { 1549 TEST 1550 } 1551 1552 @Serializable 1553 private class EnumWrapper { 1554 enum class NestedEnum { 1555 ONE, 1556 TWO 1557 } 1558 } 1559 } 1560 1561 enum class TestTopLevelEnum { 1562 TEST 1563 } 1564