@@ -698,3 +698,214 @@ test('should decode matching optional fields if wire type contains additional fi
698698 b : [ '123' ] ,
699699 } ) ;
700700} ) ;
701+
702+
703+ describe ( 'IDL opt variant decoding' , ( ) => {
704+ it ( 'should handle matching expected and wire type variants' , ( ) => {
705+ testDecode (
706+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null , z : IDL . Null } ) ) } ) ,
707+ { a : [ { x : null } ] } ,
708+ '4449444c036c0161016e026b03787f797f7a7f01000100' , // Motoko: {a = ?#x} : {a : ?{#x;#y;#z}},
709+ 'same variant under opt x' ,
710+ ) ;
711+ } ) ;
712+ it ( 'should handle matching expected and wire type variants' , ( ) => {
713+ testDecode (
714+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null , z : IDL . Null } ) ) } ) ,
715+ { a : [ { z : null } ] } ,
716+ '4449444c036c0161016e026b03787f797f7a7f01000102' , // Motoko: {a = ?#z} : {a : ?{#x;#y;#z}}
717+ 'same variant under opt z' ,
718+ ) ;
719+ } ) ;
720+ it ( 'should handle wider variant with expected tag' , ( ) => {
721+ testDecode (
722+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) } ) ,
723+ { a : [ { x : null } ] } ,
724+ '4449444c036c0161016e026b03787f797f7a7f01000100' , // Motoko: {a = ?#x} : {a : ?{#x;#y;#z}}
725+ 'extended variant under opt expected tag' ,
726+ ) ;
727+ } ) ;
728+ it ( 'should handle wider variant with unexpected tag' , ( ) => {
729+ testDecode (
730+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) } ) ,
731+ { a : [ ] } ,
732+ '4449444c036c0161016e026b03787f797f7a7f01000102' , // Motoko: {a = ?#z} : {a : ?{#x;#y;#z}}
733+ 'extended variant under opt unexpected tag - defaulting' ,
734+ ) ;
735+ } ) ;
736+ } ) ;
737+
738+ describe ( 'IDL opt edge cases' , ( ) => {
739+ it ( 'should handle the option when the wire type is null type' , ( ) => {
740+ testDecode (
741+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) } ) ,
742+ { a : [ ] } ,
743+ '4449444c016c01617f0100' ,
744+ // Motoko: {a = null} : {a : null}
745+ 'opt expected type null on wire' ,
746+ ) } ) ;
747+ it ( 'should handle the option when the wire type is reserved' , ( ) => {
748+ testDecode (
749+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) } ) ,
750+ { a : [ ] } ,
751+ '4449444c016c0161700100' ,
752+ // Motoko: {a = (): Any} : {a : Any}
753+ 'opt expected type reserved on wire' ,
754+ ) } ) ;
755+ it ( 'should handle the option when the wire typ is non-optioned' , ( ) => {
756+ testDecode (
757+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) } ) ,
758+ { a : [ { x : null } ] } ,
759+ `4449444c026c0161016b02787f797f010000` ,
760+ // Motoko: {a = #x } : {a : {#x;#y}}
761+ 'opt expected type non-opt on wire' ,
762+ ) } ) ;
763+ it ( 'should handle the option when the wire typ is an non-optioned wider variant with expected tag' , ( ) => {
764+ testDecode (
765+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) } ) ,
766+ { a : [ { x : null } ] } ,
767+ `4449444c026c0161016b03787f797f7a7f010000` ,
768+ // Motoko: {a = #x } : {a : {#x;#y;#z}}
769+ 'opt expected, wire type non-opt, extended, with expected tag' ,
770+ ) } ) ;
771+ it ( 'should handle the option when the wire typ is an non-optioned wider variant with unexpected tag, defaulting' , ( ) => {
772+ testDecode (
773+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) } ) ,
774+ { a : [ ] } ,
775+ `4449444c026c0161016b03787f797f7a7f010002` ,
776+ // Motoko: {a = #z} : {a : {#x;#y;#z}}
777+ 'opt expected, wire type non-opt, extended, with unexpected tag, defaulting' ,
778+ ) } ) ;
779+ it ( 'should handle the option when the expected type is opt null, wire type is non-opt' , ( ) => {
780+ testDecode (
781+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { a : IDL . Opt ( IDL . Null ) } ) ) } ) ,
782+ { a : [ ] } ,
783+ `4449444c016c01617d010001` ,
784+ // Motoko: {a = 1} : {a : Nat }
785+ 'opt expected, wire type non-opt, other type - defaulting' ,
786+ ) } ) ;
787+ it ( 'should handle the option when the expected type is opt opt Nat, wire type is non-opt' , ( ) => {
788+ testDecode (
789+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { a : IDL . Opt ( IDL . Opt ( IDL . Nat ) ) } ) ) } ) ,
790+ { a : [ ] } ,
791+ `4449444c016c01617d010001` ,
792+ // Motoko: {a = 1} : {a : Nat }
793+ 'opt expected, wire type non-opt, other type - defaulting' ,
794+ ) } ) ;
795+ it ( 'should handle the option when the expected type is opt reserved, wire type is non-opt' , ( ) => {
796+ testDecode (
797+ IDL . Record ( { a : IDL . Opt ( IDL . Reserved ) } ) ,
798+ { a : [ ] } ,
799+ `4449444c016c01617d010001` ,
800+ // Motoko: {a = 1} : {a : Nat }
801+ 'opt expected, wire type non-opt, other type - defaulting' ,
802+ ) } ) ;
803+ } ) ;
804+
805+
806+
807+ /* The following suites are similar to the previous two but require more decoding of a Text value following the optional value.
808+ Tests decoding resumed correctly after any skip
809+ */
810+
811+ describe ( 'IDL opt variant decoding (embedded)' , ( ) => {
812+ it ( 'should handle matching expected and wire type variants' , ( ) => {
813+ testDecode (
814+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null , z : IDL . Null } ) ) , b : IDL . Text } ) ,
815+ { a : [ { x : null } ] , b : "abc" } ,
816+ '4449444c036c02610162716e026b03787f797f7a7f0100010003616263' , // Motoko: {a = ?#x; b = "abc"} : {a : ?{#x;#y;#z}; b :Text },
817+ 'same variant under opt x' ,
818+ ) ;
819+ } ) ;
820+ it ( 'should handle matching expected and wire type variants' , ( ) => {
821+ testDecode (
822+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null , z : IDL . Null } ) ) , b : IDL . Text } ) ,
823+ { a : [ { z : null } ] , b : "abc" } ,
824+ '4449444c036c02610162716e026b03787f797f7a7f0100010203616263' , // Motoko: {a = ?#z; b = "abc"} : {a : ?{#x;#y;#z}; b : Text }
825+ 'same variant under opt z' ,
826+ ) ;
827+ } ) ;
828+ it ( 'should handle wider variant with expected tag' , ( ) => {
829+ testDecode (
830+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) , b : IDL . Text } ) ,
831+ { a : [ { x : null } ] , b : "abc" } ,
832+ '4449444c036c02610162716e026b03787f797f7a7f0100010003616263' , // Motoko: {a = ?#x; b = "abc"} : {a : ?{#x;#y;#z}; b : Text }
833+ 'extended variant under opt expected tag' ,
834+ ) ;
835+ } ) ;
836+ it ( 'should handle wider variant with unexpected tag' , ( ) => {
837+ testDecode (
838+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) , b : IDL . Text } ) ,
839+ { a : [ ] , b : "abc" } ,
840+ '4449444c036c02610162716e026b03787f797f7a7f0100010203616263' , // Motoko: {a = ?#z; b = "abc"} : {a : ?{#x;#y;#z}; b : Text }
841+ 'extended variant under opt unexpected tag - defaulting' ,
842+ ) ;
843+ } ) ;
844+ } ) ;
845+
846+ describe ( 'IDL opt edge cases (embedded)' , ( ) => {
847+ it ( 'should handle the option when the wire type is null type' , ( ) => {
848+ testDecode (
849+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) , b : IDL . Text } ) ,
850+ { a : [ ] , b : "abc" } ,
851+ '4449444c016c02617f6271010003616263' ,
852+ // Motoko: {a = null; b = "abc"} : {a : null; b: Text}
853+ 'opt expected type null on wire' ,
854+ ) } ) ;
855+ it ( 'should handle the option when the wire type is reserved' , ( ) => {
856+ testDecode (
857+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) , b : IDL . Text } ) ,
858+ { a : [ ] , b : "abc" } ,
859+ '4449444c016c0261706271010003616263' ,
860+ // Motoko: {a = (): Any; b = "abc"} : {a : Any; b : Text}
861+ 'opt expected type reserved on wire' ,
862+ ) } ) ;
863+ it ( 'should handle the option when the wire typ is non-optioned' , ( ) => {
864+ testDecode (
865+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) , b : IDL . Text } ) ,
866+ { a : [ { x : null } ] , b : "abc" } ,
867+ `4449444c026c02610162716b02787f797f01000003616263` ,
868+ // Motoko: {a = #x; b = "abc" } : {a : {#x;#y}; b : Text }
869+ 'opt expected type non-opt on wire' ,
870+ ) } ) ;
871+ it ( 'should handle the option when the wire typ is an non-optioned wider variant with expected tag' , ( ) => {
872+ testDecode (
873+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) , b : IDL . Text } ) ,
874+ { a : [ { x : null } ] , b : "abc" } ,
875+ `4449444c026c02610162716b03787f797f7a7f01000003616263` ,
876+ // Motoko: {a = #x; b = "abc" } : {a : {#x;#y;#z}; b : Text }
877+ 'opt expected, wire type non-opt, extended, with expected tag' ,
878+ ) } ) ;
879+ it ( 'should handle the option when the wire typ is an non-optioned wider variant with unexpected tag, defaulting' , ( ) => {
880+ testDecode (
881+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { x : IDL . Null , y : IDL . Null } ) ) , b : IDL . Text } ) ,
882+ { a : [ ] , b : "abc" } ,
883+ `4449444c026c02610162716b03787f797f7a7f01000203616263` ,
884+ // Motoko: {a = #z; b = "abc"} : {a : Nat; b : Text}
885+ 'opt expected, wire type non-opt, extended, with unexpected tag - defaulting' ,
886+ ) } ) ;
887+ it ( 'should handle the option when the expected type is opt null, wire type is non-opt' , ( ) => {
888+ testDecode (
889+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { a : IDL . Opt ( IDL . Null ) } ) ) , b : IDL . Text } ) ,
890+ { a : [ ] , b : "abc" } ,
891+ `4449444c036c02610162716e026b03787f797f7a7f0100010203616263` ,
892+ // Motoko: {a = 1; b = "abc"} : {a : Nat; b : Text }
893+ 'opt expected, wire type non-opt, other type - defaulting' ,
894+ ) } ) ;
895+ it ( 'should handle the option when the expected type is opt opt Nat, wire type is non-opt' , ( ) => {
896+ testDecode (
897+ IDL . Record ( { a : IDL . Opt ( IDL . Variant ( { a : IDL . Opt ( IDL . Opt ( IDL . Nat ) ) } ) ) , b : IDL . Text } ) ,
898+ { a : [ ] , b : "abc" } ,
899+ `4449444c016c02617d627101000103616263` ,
900+ // Motoko: {a = 1; b = "abc"} : {a : Nat; b : Text }
901+ 'opt expected, wire type non-opt, other type - defaulting' ,
902+ ) } ) ;
903+ it ( 'should handle the option when the expected type is opt reserved, wire type is non-opt' , ( ) => {
904+ testDecode (
905+ IDL . Record ( { a : IDL . Opt ( IDL . Reserved ) , b : IDL . Text } ) ,
906+ { a : [ ] , b : "abc" } ,
907+ `4449444c016c02617d627101000103616263` ,
908+ // Motoko: {a = 1; b = "abc"} : {a : Nat; b : Text }
909+ 'opt expected, wire type non-opt, other type - defaulting' ,
910+ ) } ) ;
911+ } ) ;
0 commit comments