55package kotlinx.serialization.cbor
66
77import kotlinx.serialization.*
8+ import kotlinx.serialization.cbor.internal.*
89import kotlin.test.*
910
1011class CborElementTest {
@@ -330,6 +331,7 @@ class CborElementTest {
330331 encodeKeyTags = true
331332 verifyKeyTags = true
332333 verifyObjectTags = true
334+ verifyValueTags = true
333335 },
334336 MixedBag (
335337 str = " A string, is a string, is a string" ,
@@ -356,10 +358,11 @@ class CborElementTest {
356358 encodeKeyTags = true
357359 verifyKeyTags = true
358360 verifyObjectTags = true
361+ verifyValueTags = true
359362 },
360363 MixedBag (
361364 str = " A string, is a string, is a string" ,
362- bStr = null ,
365+ bStr = null ,
363366 cborElement = CborBoolean (false ),
364367 cborPositiveInt = CborPositiveInt (1u ),
365368 cborInt = CborInt (- 1 ),
@@ -383,11 +386,12 @@ class CborElementTest {
383386 encodeKeyTags = true
384387 verifyKeyTags = true
385388 verifyObjectTags = true
389+ verifyValueTags = true
386390 },
387391 MixedBag (
388392 str = " A string, is a string, is a string" ,
389- bStr = null ,
390- cborElement = CborMap (mapOf (CborByteString (byteArrayOf(1 ,3 , 3 , 7 )) to CborNull ())),
393+ bStr = null ,
394+ cborElement = CborMap (mapOf (CborByteString (byteArrayOf(1 , 3 , 3 , 7 )) to CborNull ())),
391395 cborPositiveInt = CborPositiveInt (1u ),
392396 cborInt = CborInt (- 1 ),
393397 tagged = 26
@@ -411,10 +415,11 @@ class CborElementTest {
411415 encodeKeyTags = true
412416 verifyKeyTags = true
413417 verifyObjectTags = true
418+ verifyValueTags = true
414419 },
415420 MixedBag (
416421 str = " A string, is a string, is a string" ,
417- bStr = null ,
422+ bStr = null ,
418423 cborElement = CborNull (),
419424 cborPositiveInt = CborPositiveInt (1u ),
420425 cborInt = CborInt (- 1 ),
@@ -438,10 +443,11 @@ class CborElementTest {
438443 encodeKeyTags = true
439444 verifyKeyTags = true
440445 verifyObjectTags = true
446+ verifyValueTags = true
441447 },
442448 MixedBag (
443449 str = " A string, is a string, is a string" ,
444- bStr = CborByteString (byteArrayOf(), 1u ,3u ),
450+ bStr = CborByteString (byteArrayOf(), 1u , 3u ),
445451 cborElement = CborBoolean (false ),
446452 cborPositiveInt = CborPositiveInt (1u ),
447453 cborInt = CborInt (- 1 ),
@@ -457,6 +463,150 @@ class CborElementTest {
457463 assertEquals(obj, cbor.decodeFromCbor(struct))
458464 assertEquals(obj, cbor.decodeFromHexString(hex))
459465 }
466+
467+ Triple (
468+ Cbor {
469+ encodeValueTags = false
470+ encodeKeyTags = true
471+ verifyKeyTags = true
472+ verifyObjectTags = true
473+ verifyValueTags = false
474+ },
475+ MixedBag (
476+ str = " A string, is a string, is a string" ,
477+ bStr = CborByteString (byteArrayOf(), 1u , 3u ),
478+ cborElement = CborBoolean (false ),
479+ cborPositiveInt = CborPositiveInt (1u ),
480+ cborInt = CborInt (- 1 ),
481+ tagged = 26
482+ ),
483+ " bf6373747278224120737472696e672c206973206120737472696e672c206973206120737472696e676462537472c1c3406b63626f72456c656d656e74f46f63626f72506f736974697665496e74016763626f72496e7420d82a66746167676564181aff"
484+ )
485+ .let { (cbor, obj, hex) ->
486+ val struct = cbor.encodeToCbor(obj)
487+ assertEquals(hex, cbor.encodeToHexString(obj))
488+ assertEquals(hex, cbor.encodeToHexString(struct))
489+ assertEquals(struct, cbor.decodeFromHexString<CborElement >(hex))
490+ assertEquals(obj, cbor.decodeFromCbor(struct))
491+ assertEquals(obj, cbor.decodeFromHexString(hex))
492+ }
493+
494+ Triple (
495+ Cbor {
496+ encodeValueTags = true
497+ encodeKeyTags = true
498+ verifyKeyTags = true
499+ verifyObjectTags = true
500+ verifyValueTags = true
501+ },
502+ MixedTag (
503+ cborElement = CborBoolean (false ),
504+ ),
505+ " bfd82a6b63626f72456c656d656e74d90921f4ff"
506+ )
507+ .let { (cbor, obj, hex) ->
508+ val struct = cbor.encodeToCbor(obj)
509+ assertEquals(hex, cbor.encodeToHexString(obj))
510+ assertEquals(hex, cbor.encodeToHexString(struct))
511+ assertEquals(struct, cbor.decodeFromHexString<CborElement >(hex))
512+ // this is ambiguous. the cborBoolean has a tag attached in the struct, coming from the valueTag (as intended),
513+ // so now the resulting object won't have a tag but the cborElement property will have a tag attached
514+ // hence, the following two will have:
515+ // Expected :MixedTag(cborElement=CborPrimitive(kind=Boolean, tags=, value=false))
516+ // Actual :MixedTag(cborElement=CborPrimitive(kind=Boolean, tags=2337, value=false))
517+ assertNotEquals(obj, cbor.decodeFromCbor(struct))
518+ assertNotEquals(obj, cbor.decodeFromHexString(hex))
519+ }
520+ Triple (
521+ Cbor {
522+ encodeValueTags = true
523+ encodeKeyTags = true
524+ verifyKeyTags = true
525+ verifyObjectTags = true
526+ verifyValueTags = true
527+ },
528+ MixedTag (
529+ cborElement = CborBoolean (false , 90u ),
530+ ),
531+ // valueTags first, then CborElement tags
532+ " bfd82a6b63626f72456c656d656e74d90921d85af4ff"
533+ )
534+ .let { (cbor, obj, hex) ->
535+ val struct = cbor.encodeToCbor(obj)
536+ assertEquals(hex, cbor.encodeToHexString(obj))
537+ assertEquals(hex, cbor.encodeToHexString(struct))
538+ assertEquals(struct, cbor.decodeFromHexString<CborElement >(hex))
539+ // this is ambiguous. the cborBoolean has a tag attached in the struct, coming from the valueTag (as intended),
540+ // so now the resulting object won't have a tag but the cborElement property will have a tag attached
541+ // hence, the following two will have:
542+ // Expected :MixedTag(cborElement=CborPrimitive(kind=Boolean, tags=90, value=false))
543+ // Actual :MixedTag(cborElement=CborPrimitive(kind=Boolean, tags=2337, 90, value=false))
544+ // of course, the value tag verification will also fail hard
545+ assertFailsWith(
546+ CborDecodingException ::class ,
547+ " CBOR tags [2337, 90] do not match expected tags [2337]"
548+ ) {
549+ assertNotEquals(obj, cbor.decodeFromCbor(struct))
550+ }
551+ assertFailsWith(
552+ CborDecodingException ::class ,
553+ " CBOR tags [2337, 90] do not match expected tags [2337]"
554+ ) {
555+ assertNotEquals(obj, cbor.decodeFromHexString(hex))
556+ }
557+ }
558+
559+ Triple (
560+ Cbor {
561+ encodeValueTags = true
562+ encodeKeyTags = true
563+ verifyKeyTags = true
564+ verifyObjectTags = true
565+ verifyValueTags = false
566+ },
567+ MixedTag (
568+ cborElement = CborBoolean (false , 90u ),
569+ ),
570+ // valueTags first, then CborElement tags
571+ " bfd82a6b63626f72456c656d656e74d90921d85af4ff"
572+ )
573+ .let { (cbor, obj, hex) ->
574+ val struct = cbor.encodeToCbor(obj)
575+ assertEquals(hex, cbor.encodeToHexString(obj))
576+ assertEquals(hex, cbor.encodeToHexString(struct))
577+ assertEquals(struct, cbor.decodeFromHexString<CborElement >(hex))
578+ // this is ambiguous. the cborBoolean has a tag attached in the struct, coming from the valueTag (as intended),
579+ // so now the resulting object won't have a tag but the cborElement property will have a tag attached
580+ // hence, the following two will have:
581+ // Expected :MixedTag(cborElement=CborPrimitive(kind=Boolean, tags=90, value=false))
582+ // Actual :MixedTag(cborElement=CborPrimitive(kind=Boolean, tags=2337, 90, value=false))
583+ assertNotEquals(obj, cbor.decodeFromCbor(struct))
584+ assertNotEquals(obj, cbor.decodeFromHexString(hex))
585+ }
586+
587+
588+ Triple (
589+ Cbor {
590+ encodeValueTags = false
591+ encodeKeyTags = true
592+ verifyKeyTags = true
593+ verifyObjectTags = true
594+ verifyValueTags = false
595+ },
596+ MixedTag (
597+ cborElement = CborBoolean (false , 90u ),
598+ ),
599+ " bfd82a6b63626f72456c656d656e74d85af4ff"
600+ )
601+ .let { (cbor, obj, hex) ->
602+ val struct = cbor.encodeToCbor(obj)
603+ assertEquals(hex, cbor.encodeToHexString(obj))
604+ assertEquals(hex, cbor.encodeToHexString(struct))
605+ assertEquals(struct, cbor.decodeFromHexString<CborElement >(hex))
606+ // no value tags means everything's fine again
607+ assertEquals(obj, cbor.decodeFromCbor(struct))
608+ assertEquals(obj, cbor.decodeFromHexString(hex))
609+ }
460610 }
461611
462612}
@@ -472,3 +622,11 @@ data class MixedBag(
472622 @ValueTags(2337u )
473623 val tagged : Int
474624)
625+
626+
627+ @Serializable
628+ data class MixedTag (
629+ @KeyTags(42u )
630+ @ValueTags(2337u )
631+ val cborElement : CborElement ? ,
632+ )
0 commit comments