From 2a8672e2a3c73ee4d10c49fa00ff4692a9496769 Mon Sep 17 00:00:00 2001
From: Lev Walkin <vlm@lionet.info>
Date: Sun, 3 Oct 2004 09:14:49 +0000
Subject: [PATCH] CANONICAL-XER testing

---
 asn1c/tests/check-30.c        |  66 +++++++++++++++----
 asn1c/tests/check-31.c        |  36 +++++++++++
 asn1c/tests/check-35.c        |  39 +++++++++++-
 tests/30-set-OK.asn1          |   6 +-
 tests/30-set-OK.asn1.-P       | 109 +++++++++++++++++++++++++++++++
 tests/31-set-of-OK.asn1       |  10 ++-
 tests/31-set-of-OK.asn1.-EF   |  11 +++-
 tests/31-set-of-OK.asn1.-P    | 117 +++++++++++++++++++++++++++++-----
 tests/43-recursion-OK.asn1.-P |   4 ++
 tests/47-set-ext-OK.asn1.-P   |   4 ++
 10 files changed, 364 insertions(+), 38 deletions(-)
 create mode 100644 tests/30-set-OK.asn1.-P

diff --git a/asn1c/tests/check-30.c b/asn1c/tests/check-30.c
index 3389d539..c1528b9f 100644
--- a/asn1c/tests/check-30.c
+++ b/asn1c/tests/check-30.c
@@ -53,12 +53,12 @@ uint8_t buf3[] = {
 	32 | 17,		/* [UNIVERSAL 17], constructed */
 	14,	/* L */
 
-	/* a INTEGER */
+	/* INTEGER */
 	64 | 3,			/* [APPLICATION 3] */
 	1,	/* L */
   96,
 
-	/* b IA5String */
+	/* IA5String */
 	22,			/* [UNIVERSAL 22] */
 	3,	/* L */
 	'x',
@@ -70,7 +70,7 @@ uint8_t buf3[] = {
 	1,	/* L */
   96,
 
-	/* c [2] BOOLEAN */
+	/* [2] BOOLEAN */
 	((2 << 6) + 2),			/* [2] */
 	1,	/* L */
 	0xff
@@ -115,12 +115,12 @@ uint8_t buf5[] = {
 	32 | 17,		/* [UNIVERSAL 17], constructed */
 	0x80,	/* indefinite L */
 
-	/* a INTEGER */
+	/* INTEGER */
 	64 | 3,			/* [APPLICATION 3] */
 	1,	/* L */
   96,
 
-	/* b IA5String */
+	/* IA5String */
 	22,			/* [UNIVERSAL 22] */
 	3,	/* L */
 	'x',
@@ -159,26 +159,61 @@ check(int is_ok, uint8_t *buf, int size, size_t consumed) {
 		assert(rval.code == RC_OK);
 		assert(rval.consumed == consumed);
 
-		assert(t.a.size == 1);
-		assert(t.a.buf[0] == 96);
-		assert(t.b.size == 3);
-		assert(strcmp(t.b.buf, "xyz") == 0);
+		assert(t.i.size == 1);
+		assert(t.i.buf[0] == 96);
+		assert(t.s.size == 3);
+		assert(strcmp(t.s.buf, "xyz") == 0);
 		if(buf == buf3) {
-			assert(t.c);
+			assert(t.b);
 		} else {
-			assert(t.c == 0);
+			assert(t.b == 0);
 		}
 	} else {
 		if(rval.code == RC_OK) {
-			assert(t.a.size != 1
-			|| t.b.size != 3
-			|| !t.c
+			assert(t.i.size != 1
+			|| t.s.size != 3
+			|| !t.b
 			);
 		}
 		assert(rval.consumed <= consumed);
 	}
 }
 
+
+static char xer_buf[128];
+static int xer_off;
+
+static int
+xer_cb(const void *buffer, size_t size, void *key) {
+	(void)key;
+	assert(xer_off + size < sizeof(xer_buf));
+	memcpy(xer_buf + xer_off, buffer, size);
+	xer_off += size;
+	return 0;
+}
+
+static void
+check_xer(uint8_t *buf, uint8_t size, char *xer_sample) {
+	T_t *tp = 0;
+	ber_dec_rval_t rval;
+	asn_enc_rval_t er;
+	int xer_sample_len = strlen(xer_sample);
+
+	rval = ber_decode(0, &asn_DEF_T, (void **)&tp, buf, size);
+	assert(rval.code == RC_OK);
+	assert(rval.consumed == size);
+	assert(tp);
+
+	xer_off = 0;
+	er = xer_encode(&asn_DEF_T, tp, XER_F_CANONICAL, xer_cb, 0);
+	assert(er.encoded == xer_off);
+	assert(xer_off);
+	xer_buf[xer_off] = 0;
+	printf("[%s] vs [%s]\n", xer_buf, xer_sample);
+	assert(xer_off = xer_sample_len);
+	assert(memcmp(xer_buf, xer_sample, xer_off) == 0);
+}
+
 static void
 try_corrupt(uint8_t *buf, int size) {
 	uint8_t *tmp;
@@ -219,6 +254,9 @@ main(int ac, char **av) {
 	check(1, buf5, sizeof(buf5) + 1, sizeof(buf5));
 	check(0, buf5, sizeof(buf5) - 1, sizeof(buf5));
 
+	check_xer(buf1, sizeof(buf1), "<T><s>xyz</s><i>96</i></T>");
+	check_xer(buf3, sizeof(buf3), "<T><s>xyz</s><i>96</i><b><true/></b></T>");
+
 	fprintf(stderr, "\nPseudo-random buffer corruptions must fail\n");
 	try_corrupt(buf1, sizeof(buf1));
 
diff --git a/asn1c/tests/check-31.c b/asn1c/tests/check-31.c
index 06ad6b55..5c5075c4 100644
--- a/asn1c/tests/check-31.c
+++ b/asn1c/tests/check-31.c
@@ -141,6 +141,41 @@ check(int is_ok, uint8_t *buf, int size, size_t consumed) {
 	asn_DEF_Forest.free_struct(&asn_DEF_Forest, &t, 1);
 }
 
+static char xer_buf[512];
+static int xer_off;
+
+static int
+xer_cb(const void *buffer, size_t size, void *key) {
+	(void)key;
+	assert(xer_off + size < sizeof(xer_buf));
+	memcpy(xer_buf + xer_off, buffer, size);
+	xer_off += size;
+	return 0;
+}
+
+static void
+check_xer(uint8_t *buf, uint8_t size, char *xer_sample) {
+	Forest_t *tp = 0;
+	ber_dec_rval_t rval;
+	asn_enc_rval_t er;
+	int xer_sample_len = strlen(xer_sample);
+
+	rval = ber_decode(0, &asn_DEF_Forest, (void **)&tp, buf, size);
+	assert(rval.code == RC_OK);
+	assert(rval.consumed == size);
+	assert(tp);
+
+	xer_off = 0;
+	er = xer_encode(&asn_DEF_Forest, tp, XER_F_CANONICAL, xer_cb, 0);
+	assert(er.encoded == xer_off);
+	assert(xer_off);
+	xer_buf[xer_off] = 0;
+	printf("[%s] vs [%s]\n", xer_buf, xer_sample);
+	assert(xer_off = xer_sample_len);
+	assert(memcmp(xer_buf, xer_sample, xer_off) == 0);
+}
+
+
 static void
 try_corrupt(uint8_t *buf, int size) {
 	uint8_t *tmp;
@@ -174,6 +209,7 @@ main(int ac, char **av) {
 	(void)av;	/* Unused argument */
 
 	check(1, buf1, sizeof(buf1), sizeof(buf1));
+	check_xer(buf1, sizeof(buf1), "<Forest><Tree><height>100</height><width>80</width></Tree><Tree><height>110</height><width>82</width></Tree></Forest>");
 	try_corrupt(buf1, sizeof(buf1));
 	check(1, buf1, sizeof(buf1) + 20, sizeof(buf1));
 
diff --git a/asn1c/tests/check-35.c b/asn1c/tests/check-35.c
index f5404518..87994c91 100644
--- a/asn1c/tests/check-35.c
+++ b/asn1c/tests/check-35.c
@@ -203,7 +203,7 @@ partial_read(uint8_t *buf, size_t size) {
 	/*
 	 * Divide the space (size) into three blocks in various combinations:
 	 *   |<----->i1<----->i2<----->|
-	 *   ^ buf                     ^ buf+size
+	 *   ^ buf		     ^ buf+size
 	 * Try to read block by block.
 	 */
 	for(i1 = 0; i1 < size; i1++) {
@@ -262,6 +262,41 @@ partial_read(uint8_t *buf, size_t size) {
 	}
 }
 
+static char xer_buf[128];
+static int xer_off;
+
+static int
+xer_cb(const void *buffer, size_t size, void *key) {
+	(void)key;
+	assert(xer_off + size < sizeof(xer_buf));
+	memcpy(xer_buf + xer_off, buffer, size);
+	xer_off += size;
+	return 0;
+}
+
+static void
+check_xer(uint8_t *buf, uint8_t size, char *xer_sample) {
+	T_t *tp = 0;
+	ber_dec_rval_t rval;
+	asn_enc_rval_t er;
+	int xer_sample_len = strlen(xer_sample);
+
+	rval = ber_decode(0, &asn_DEF_T, (void **)&tp, buf, size);
+	assert(rval.code == RC_OK);
+	assert(rval.consumed == size);
+	assert(tp);
+
+	xer_off = 0;
+	er = xer_encode(&asn_DEF_T, tp, XER_F_CANONICAL, xer_cb, 0);
+	assert(er.encoded == xer_off);
+	assert(xer_off);
+	xer_buf[xer_off] = 0;
+	printf("[%s] vs [%s]\n", xer_buf, xer_sample);
+	assert(xer_off = xer_sample_len);
+	assert(memcmp(xer_buf, xer_sample, xer_off) == 0);
+}
+
+
 int
 main(int ac, char **av) {
 	T_t t;
@@ -272,10 +307,12 @@ main(int ac, char **av) {
 	check(&t, buf1, sizeof(buf1) + 10, sizeof(buf1));
 	compare(&t, buf1_reconstr, sizeof(buf1_reconstr));
 	asn_DEF_T.free_struct(&asn_DEF_T, &t, 1);
+	check_xer(buf1, sizeof(buf1), "<T><c><false/></c><b><b2>z</b2></b><a>ns</a><d><r-oid>85.79</r-oid></d></T>");
 
 	check(&t, buf2, sizeof(buf2) + 10, sizeof(buf2));
 	compare(&t, buf2_reconstr, sizeof(buf2_reconstr));
 	asn_DEF_T.free_struct(&asn_DEF_T, &t, 1);
+	check_xer(buf2, sizeof(buf2), "<T><c><true/></c><b><b1>z</b1></b><a>ns</a><d><oid>2.1</oid></d></T>");
 
 	/* Split the buffer in parts and check decoder restartability */
 	partial_read(buf1, sizeof(buf1));
diff --git a/tests/30-set-OK.asn1 b/tests/30-set-OK.asn1
index 2cd6a5a4..41ad52d3 100644
--- a/tests/30-set-OK.asn1
+++ b/tests/30-set-OK.asn1
@@ -12,10 +12,10 @@ ModuleTestSetSimple
 BEGIN
 
 	T ::= SET {
-		a [APPLICATION 3] INTEGER,
-		b IA5String,
+		i [APPLICATION 3] INTEGER,
+		s IA5String,
 		...,
-		c [2] BOOLEAN
+		b [2] BOOLEAN
 	}
 
 END
diff --git a/tests/30-set-OK.asn1.-P b/tests/30-set-OK.asn1.-P
new file mode 100644
index 00000000..1ffd9b4b
--- /dev/null
+++ b/tests/30-set-OK.asn1.-P
@@ -0,0 +1,109 @@
+
+/*** <<< INCLUDES [T] >>> ***/
+
+#include <INTEGER.h>
+#include <IA5String.h>
+#include <BOOLEAN.h>
+#include <constr_SET.h>
+
+/*** <<< DEPS [T] >>> ***/
+
+
+/*
+ * Method of determining the components presence
+ */
+typedef enum T_PR {
+	T_PR_i,	/* Member i is present */
+	T_PR_s,	/* Member s is present */
+	T_PR_b,	/* Member b is present */
+} T_PR;
+extern asn_TYPE_descriptor_t asn_DEF_T;
+
+/*** <<< TYPE-DECLS [T] >>> ***/
+
+
+typedef struct T {
+	INTEGER_t	 i;
+	IA5String_t	 s;
+	/*
+	 * This type is extensible,
+	 * possible extensions are below.
+	 */
+	BOOLEAN_t	*b;
+	
+	/* Presence bitmask: ASN_SET_ISPRESENT(pT, T_PR_x) */
+	unsigned int _presence_map
+		[((3+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];
+	
+	/* Context for parsing across buffer boundaries */
+	asn_struct_ctx_t _asn_ctx;
+} T_t;
+
+/*** <<< STAT-DEFS [T] >>> ***/
+
+static asn_TYPE_member_t asn_MBR_T[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct T, i),
+		.tag = (ASN_TAG_CLASS_APPLICATION | (3 << 2)),
+		.tag_mode = -1,	/* IMPLICIT tag at current level */
+		.type = (void *)&asn_DEF_INTEGER,
+		.memb_constraints = 0,	/* Defer to actual type */
+		.name = "i"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct T, s),
+		.tag = (ASN_TAG_CLASS_UNIVERSAL | (22 << 2)),
+		.tag_mode = 0,
+		.type = (void *)&asn_DEF_IA5String,
+		.memb_constraints = 0,	/* Defer to actual type */
+		.name = "s"
+		},
+	{ ATF_POINTER, 0, offsetof(struct T, b),
+		.tag = (ASN_TAG_CLASS_CONTEXT | (2 << 2)),
+		.tag_mode = -1,	/* IMPLICIT tag at current level */
+		.type = (void *)&asn_DEF_BOOLEAN,
+		.memb_constraints = 0,	/* Defer to actual type */
+		.name = "b"
+		},
+};
+static ber_tlv_tag_t asn_DEF_T_tags[] = {
+	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
+};
+static asn_TYPE_tag2member_t asn_DEF_T_tag2el[] = {
+    { (ASN_TAG_CLASS_UNIVERSAL | (22 << 2)), 1, 0, 0 }, /* s at 16 */
+    { (ASN_TAG_CLASS_APPLICATION | (3 << 2)), 0, 0, 0 }, /* i at 15 */
+    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 2, 0, 0 }, /* b at 18 */
+};
+static uint8_t asn_DEF_T_mmap[(3 + (8 * sizeof(unsigned int)) - 1) / 8] = {
+	(1 << 7) | (1 << 6) | (0 << 5)
+};
+static asn_SET_specifics_t asn_DEF_T_specs = {
+	sizeof(struct T),
+	offsetof(struct T, _asn_ctx),
+	offsetof(struct T, _presence_map),
+	asn_DEF_T_tag2el,
+	3,	/* Count of tags in the map */
+	asn_DEF_T_tag2el,	/* Same as above */
+	3,	/* Count of tags in the CANONICAL-XER map */
+	1,	/* Whether extensible */
+	(unsigned int *)asn_DEF_T_mmap	/* Mandatory elements map */
+};
+asn_TYPE_descriptor_t asn_DEF_T = {
+	"T",
+	SET_free,
+	SET_print,
+	SET_constraint,
+	SET_decode_ber,
+	SET_encode_der,
+	0,				/* Not implemented yet */
+	SET_encode_xer,
+	0,	/* Use generic outmost tag fetcher */
+	asn_DEF_T_tags,
+	sizeof(asn_DEF_T_tags)
+		/sizeof(asn_DEF_T_tags[0]), /* 1 */
+	asn_DEF_T_tags,	/* Same as above */
+	sizeof(asn_DEF_T_tags)
+		/sizeof(asn_DEF_T_tags[0]), /* 1 */
+	asn_MBR_T,
+	3,	/* Elements count */
+	&asn_DEF_T_specs	/* Additional specs */
+};
+
diff --git a/tests/31-set-of-OK.asn1 b/tests/31-set-of-OK.asn1
index 6f36c017..c8fa51eb 100644
--- a/tests/31-set-of-OK.asn1
+++ b/tests/31-set-of-OK.asn1
@@ -20,8 +20,14 @@ BEGIN
 
 	-- The following clause tests OPTIONAL.
 	Stuff ::= SET {
-			trees    [0] SET OF Forest OPTIONAL,
-			anything [1] SET OF
+			trees    [1] SET OF Forest OPTIONAL,
+			...,
+			other    CHOICE {
+				a [0] INTEGER,
+				b [3] INTEGER
+			},
+			...,
+			anything [2] SET OF
 				SEQUENCE {
 					cup-of-coffee	BIT STRING,
 					...
diff --git a/tests/31-set-of-OK.asn1.-EF b/tests/31-set-of-OK.asn1.-EF
index 692450b1..2efaccc5 100644
--- a/tests/31-set-of-OK.asn1.-EF
+++ b/tests/31-set-of-OK.asn1.-EF
@@ -12,11 +12,16 @@ Tree ::= SEQUENCE {
 }
 
 Stuff ::= SET {
-    trees	 [0] IMPLICIT SET OF Forest OPTIONAL,
-    anything	 [1] IMPLICIT SET OF SEQUENCE {
+    trees	 [1] IMPLICIT SET OF Forest OPTIONAL,
+    anything	 [2] IMPLICIT SET OF SEQUENCE {
             cup-of-coffee	 BIT STRING,        
             ...
-        } OPTIONAL
+        } OPTIONAL,
+    ...,
+    other	 CHOICE {
+        a	 [0] IMPLICIT INTEGER,    
+        b	 [3] IMPLICIT INTEGER
+    }
 }
 
 END
diff --git a/tests/31-set-of-OK.asn1.-P b/tests/31-set-of-OK.asn1.-P
index 37533f00..143ab8c6 100644
--- a/tests/31-set-of-OK.asn1.-P
+++ b/tests/31-set-of-OK.asn1.-P
@@ -142,6 +142,8 @@ asn_TYPE_descriptor_t asn_DEF_Tree = {
 #include <constr_SET_OF.h>
 #include <BIT_STRING.h>
 #include <constr_SEQUENCE.h>
+#include <INTEGER.h>
+#include <constr_CHOICE.h>
 #include <constr_SET.h>
 
 /*** <<< DEPS [Stuff] >>> ***/
@@ -153,7 +155,13 @@ asn_TYPE_descriptor_t asn_DEF_Tree = {
 typedef enum Stuff_PR {
 	Stuff_PR_trees,	/* Member trees is present */
 	Stuff_PR_anything,	/* Member anything is present */
+	Stuff_PR_other,	/* Member other is present */
 } Stuff_PR;
+typedef enum other_PR {
+	other_PR_NOTHING,	/* No components present */
+	other_PR_a,
+	other_PR_b,
+} other_PR;
 extern asn_TYPE_descriptor_t asn_DEF_Stuff;
 
 /*** <<< TYPE-DECLS [Stuff] >>> ***/
@@ -181,10 +189,24 @@ typedef struct Stuff {
 		/* Context for parsing across buffer boundaries */
 		asn_struct_ctx_t _asn_ctx;
 	} *anything;
+	/*
+	 * This type is extensible,
+	 * possible extensions are below.
+	 */
+	struct other {
+		other_PR present;
+		union {
+			INTEGER_t	 a;
+			INTEGER_t	 b;
+		} choice;
+		
+		/* Context for parsing across buffer boundaries */
+		asn_struct_ctx_t _asn_ctx;
+	} *other;
 	
 	/* Presence bitmask: ASN_SET_ISPRESENT(pStuff, Stuff_PR_x) */
 	unsigned int _presence_map
-		[((2+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];
+		[((3+(8*sizeof(unsigned int))-1)/(8*sizeof(unsigned int)))];
 	
 	/* Context for parsing across buffer boundaries */
 	asn_struct_ctx_t _asn_ctx;
@@ -202,7 +224,7 @@ static asn_TYPE_member_t asn_MBR_trees[] = {
 		},
 };
 static ber_tlv_tag_t asn_DEF_trees_tags[] = {
-	(ASN_TAG_CLASS_CONTEXT | (0 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
 	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
 };
 static asn_SET_OF_specifics_t asn_DEF_trees_specs = {
@@ -245,7 +267,7 @@ static ber_tlv_tag_t asn_DEF_anything_member_tags[] = {
 	(ASN_TAG_CLASS_UNIVERSAL | (16 << 2))
 };
 static asn_TYPE_tag2member_t asn_DEF_anything_member_tag2el[] = {
-    { (ASN_TAG_CLASS_UNIVERSAL | (3 << 2)), 0, 0, 0 }, /* cup-of-coffee at 26 */
+    { (ASN_TAG_CLASS_UNIVERSAL | (3 << 2)), 0, 0, 0 }, /* cup-of-coffee at 32 */
 };
 static asn_SEQUENCE_specifics_t asn_DEF_anything_member_specs = {
 	sizeof(struct anything_member),
@@ -287,7 +309,7 @@ static asn_TYPE_member_t asn_MBR_anything[] = {
 		},
 };
 static ber_tlv_tag_t asn_DEF_anything_tags[] = {
-	(ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+	(ASN_TAG_CLASS_CONTEXT | (2 << 2)),
 	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
 };
 static asn_SET_OF_specifics_t asn_DEF_anything_specs = {
@@ -317,39 +339,104 @@ asn_TYPE_descriptor_t asn_DEF_anything = {
 	&asn_DEF_anything_specs	/* Additional specs */
 };
 
-static asn_TYPE_member_t asn_MBR_Stuff[] = {
-	{ ATF_POINTER, 2, offsetof(struct Stuff, trees),
+static asn_TYPE_member_t asn_MBR_other[] = {
+	{ ATF_NOFLAGS, 0, offsetof(struct other, choice.a),
 		.tag = (ASN_TAG_CLASS_CONTEXT | (0 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
+		.type = (void *)&asn_DEF_INTEGER,
+		.memb_constraints = 0,	/* Defer to actual type */
+		.name = "a"
+		},
+	{ ATF_NOFLAGS, 0, offsetof(struct other, choice.b),
+		.tag = (ASN_TAG_CLASS_CONTEXT | (3 << 2)),
+		.tag_mode = -1,	/* IMPLICIT tag at current level */
+		.type = (void *)&asn_DEF_INTEGER,
+		.memb_constraints = 0,	/* Defer to actual type */
+		.name = "b"
+		},
+};
+static asn_TYPE_tag2member_t asn_DEF_other_tag2el[] = {
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* a at 26 */
+    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 1, 0, 0 }, /* b at 28 */
+};
+static asn_CHOICE_specifics_t asn_DEF_other_specs = {
+	sizeof(struct other),
+	offsetof(struct other, _asn_ctx),
+	offsetof(struct other, present),
+	sizeof(((struct other *)0)->present),
+	asn_DEF_other_tag2el,
+	2,	/* Count of tags in the map */
+	0	/* Whether extensible */
+};
+static /* Use -fall-defs-global to expose */
+asn_TYPE_descriptor_t asn_DEF_other = {
+	"other",
+	CHOICE_free,
+	CHOICE_print,
+	CHOICE_constraint,
+	CHOICE_decode_ber,
+	CHOICE_encode_der,
+	0,				/* Not implemented yet */
+	CHOICE_encode_xer,
+	CHOICE_outmost_tag,
+	0,	/* No effective tags (pointer) */
+	0,	/* No effective tags (count) */
+	0,	/* No tags (pointer) */
+	0,	/* No tags (count) */
+	asn_MBR_other,
+	2,	/* Elements count */
+	&asn_DEF_other_specs	/* Additional specs */
+};
+
+static asn_TYPE_member_t asn_MBR_Stuff[] = {
+	{ ATF_POINTER, 3, offsetof(struct Stuff, trees),
+		.tag = (ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn_DEF_trees,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "trees"
 		},
-	{ ATF_POINTER, 1, offsetof(struct Stuff, anything),
-		.tag = (ASN_TAG_CLASS_CONTEXT | (1 << 2)),
+	{ ATF_POINTER, 2, offsetof(struct Stuff, anything),
+		.tag = (ASN_TAG_CLASS_CONTEXT | (2 << 2)),
 		.tag_mode = -1,	/* IMPLICIT tag at current level */
 		.type = (void *)&asn_DEF_anything,
 		.memb_constraints = 0,	/* Defer to actual type */
 		.name = "anything"
 		},
+	{ ATF_POINTER, 0, offsetof(struct Stuff, other),
+		.tag = -1 /* Ambiguous tag (CHOICE?) */,
+		.tag_mode = 0,
+		.type = (void *)&asn_DEF_other,
+		.memb_constraints = 0,	/* Defer to actual type */
+		.name = "other"
+		},
 };
 static ber_tlv_tag_t asn_DEF_Stuff_tags[] = {
 	(ASN_TAG_CLASS_UNIVERSAL | (17 << 2))
 };
 static asn_TYPE_tag2member_t asn_DEF_Stuff_tag2el[] = {
-    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 0, 0, 0 }, /* trees at 23 */
-    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 1, 0, 0 }, /* anything at 28 */
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 2, 0, 0 }, /* a at 26 */
+    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* trees at 23 */
+    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 }, /* anything at 34 */
+    { (ASN_TAG_CLASS_CONTEXT | (3 << 2)), 2, 0, 0 }, /* b at 28 */
+};
+static asn_TYPE_tag2member_t asn_DEF_Stuff_tag2el_cxer[] = {
+    { (ASN_TAG_CLASS_CONTEXT | (1 << 2)), 0, 0, 0 }, /* trees at 23 */
+    { (ASN_TAG_CLASS_CONTEXT | (2 << 2)), 1, 0, 0 }, /* anything at 34 */
+    { (ASN_TAG_CLASS_CONTEXT | (0 << 2)), 2, 0, 0 }, /* a at 26 */
 };
-static uint8_t asn_DEF_Stuff_mmap[(2 + (8 * sizeof(unsigned int)) - 1) / 8] = {
-	(0 << 7) | (0 << 6)
+static uint8_t asn_DEF_Stuff_mmap[(3 + (8 * sizeof(unsigned int)) - 1) / 8] = {
+	(0 << 7) | (0 << 6) | (0 << 5)
 };
 static asn_SET_specifics_t asn_DEF_Stuff_specs = {
 	sizeof(struct Stuff),
 	offsetof(struct Stuff, _asn_ctx),
 	offsetof(struct Stuff, _presence_map),
 	asn_DEF_Stuff_tag2el,
-	2,	/* Count of tags in the map */
-	0,	/* Whether extensible */
+	4,	/* Count of tags in the map */
+	asn_DEF_Stuff_tag2el_cxer,
+	3,	/* Count of tags in the CANONICAL-XER map */
+	1,	/* Whether extensible */
 	(unsigned int *)asn_DEF_Stuff_mmap	/* Mandatory elements map */
 };
 asn_TYPE_descriptor_t asn_DEF_Stuff = {
@@ -369,7 +456,7 @@ asn_TYPE_descriptor_t asn_DEF_Stuff = {
 	sizeof(asn_DEF_Stuff_tags)
 		/sizeof(asn_DEF_Stuff_tags[0]), /* 1 */
 	asn_MBR_Stuff,
-	2,	/* Elements count */
+	3,	/* Elements count */
 	&asn_DEF_Stuff_specs	/* Additional specs */
 };
 
diff --git a/tests/43-recursion-OK.asn1.-P b/tests/43-recursion-OK.asn1.-P
index 885e6352..7f03aad7 100644
--- a/tests/43-recursion-OK.asn1.-P
+++ b/tests/43-recursion-OK.asn1.-P
@@ -396,6 +396,8 @@ static asn_SET_specifics_t asn_DEF_Test_structure_2_specs = {
 	offsetof(struct Test_structure_2, _presence_map),
 	asn_DEF_Test_structure_2_tag2el,
 	1,	/* Count of tags in the map */
+	asn_DEF_Test_structure_2_tag2el,	/* Same as above */
+	1,	/* Count of tags in the CANONICAL-XER map */
 	0,	/* Whether extensible */
 	(unsigned int *)asn_DEF_Test_structure_2_mmap	/* Mandatory elements map */
 };
@@ -479,6 +481,8 @@ static asn_SET_specifics_t asn_DEF_Test_structure_3_specs = {
 	offsetof(struct Test_structure_3, _presence_map),
 	asn_DEF_Test_structure_3_tag2el,
 	1,	/* Count of tags in the map */
+	asn_DEF_Test_structure_3_tag2el,	/* Same as above */
+	1,	/* Count of tags in the CANONICAL-XER map */
 	0,	/* Whether extensible */
 	(unsigned int *)asn_DEF_Test_structure_3_mmap	/* Mandatory elements map */
 };
diff --git a/tests/47-set-ext-OK.asn1.-P b/tests/47-set-ext-OK.asn1.-P
index 568caadc..5aa2ce2d 100644
--- a/tests/47-set-ext-OK.asn1.-P
+++ b/tests/47-set-ext-OK.asn1.-P
@@ -59,6 +59,8 @@ static asn_SET_specifics_t asn_DEF_T1_specs = {
 	offsetof(struct T1, _presence_map),
 	asn_DEF_T1_tag2el,
 	1,	/* Count of tags in the map */
+	asn_DEF_T1_tag2el,	/* Same as above */
+	1,	/* Count of tags in the CANONICAL-XER map */
 	1,	/* Whether extensible */
 	(unsigned int *)asn_DEF_T1_mmap	/* Mandatory elements map */
 };
@@ -144,6 +146,8 @@ static asn_SET_specifics_t asn_DEF_T2_specs = {
 	offsetof(struct T2, _presence_map),
 	asn_DEF_T2_tag2el,
 	1,	/* Count of tags in the map */
+	asn_DEF_T2_tag2el,	/* Same as above */
+	1,	/* Count of tags in the CANONICAL-XER map */
 	1,	/* Whether extensible */
 	(unsigned int *)asn_DEF_T2_mmap	/* Mandatory elements map */
 };
-- 
GitLab