1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2013-2016. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21-module(error_SUITE).
22-export([suite/0,all/0,groups/0,
23	 already_defined/1,bitstrings/1,
24	 classes/1,constraints/1,constructed/1,enumerated/1,
25	 imports_exports/1,instance_of/1,integers/1,objects/1,
26	 object_field_extraction/1,oids/1,rel_oids/1,
27	 object_sets/1,parameterization/1,
28	 syntax/1,table_constraints/1,tags/1,values/1]).
29
30-include_lib("common_test/include/ct.hrl").
31
32suite() -> [{ct_hooks, [ts_install_cth]}].
33
34all() ->
35    [{group,p}].
36
37groups() ->
38    [{p,parallel(),
39      [already_defined,
40       bitstrings,
41       classes,
42       constraints,
43       constructed,
44       enumerated,
45       imports_exports,
46       instance_of,
47       integers,
48       objects,
49       object_field_extraction,
50       object_sets,
51       oids,
52       rel_oids,
53       parameterization,
54       syntax,
55       table_constraints,
56       tags,
57       values]}].
58
59parallel() ->
60    case erlang:system_info(schedulers) > 1 of
61        true  -> [parallel];
62        false -> []
63    end.
64
65already_defined(Config) ->
66    M = 'Already',
67    P = {M,
68	 <<"Already DEFINITIONS ::= BEGIN\n"
69	   "  I ::= INTEGER\n"
70	   "  i I ::= 42\n"
71	   "  I ::= OCTET STRING\n"
72	   "  I ::= CLASS { &Type }\n"
73	   "  MYCLASS ::= CLASS { &Type }\n"
74	   "  i MYCLASS ::= { &Type INTEGER }\n"
75	   "  o MYCLASS ::= { &Type INTEGER }\n"
76	   "  I MYCLASS ::= { o }\n"
77	   "  I{T} ::= SEQUENCE OF T\n"
78	   "  I{INTEGER:x} INTEGER ::= { 1 | 2 | x }\n"
79	   "  i{T} MYCLASS ::= { &Type T }\n"
80	   "END\n">>},
81    {error,
82     [
83      {structured_error,{M,4},asn1ct_check,{already_defined,'I',2}},
84      {structured_error,{M,5},asn1ct_check,{already_defined,'I',2}},
85      {structured_error,{M,7},asn1ct_check,{already_defined,'i',3}},
86      {structured_error,{M,9},asn1ct_check,{already_defined,'I',2}},
87      {structured_error,{M,10},asn1ct_check,{already_defined,'I',2}},
88      {structured_error,{M,11},asn1ct_check,{already_defined,'I',2}},
89      {structured_error,{M,12},asn1ct_check,{already_defined,'i',3}}
90     ]
91    } = run(P, Config),
92    ok.
93
94bitstrings(Config) ->
95    M = 'Bitstrings',
96    P = {M,
97	 <<"Bitstrings DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
98	   "  Bs1 ::= BIT STRING {a(1), a(1)}\n"
99	   "  Bs2 ::= BIT STRING {a(1), b(2), a(3)}\n"
100	   "  Bs3 ::= BIT STRING {x(1), y(1)}\n"
101	   "  Bs4 ::= BIT STRING {x(-1), y(0)}\n"
102	   "END\n">>},
103    {error,
104     [{structured_error,{M,2},asn1ct_check,{namelist_redefinition,a}},
105      {structured_error,{M,3},asn1ct_check,{namelist_redefinition,a}},
106      {structured_error,{M,4},asn1ct_check,{value_reused,1}},
107      {structured_error,{M,5},asn1ct_check,{invalid_bit_number,-1}}
108     ]} = run(P, Config),
109    ok.
110
111classes(Config) ->
112    M = 'Classes',
113    P = {M,
114	 <<"Classes DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
115	   "  LowerCase ::= CLASS { &id INTEGER UNIQUE }\n"
116	   "  CL ::= CLASS { &id INTEGER UNIQUE DEFAULT 42}\n"
117	   "END\n">>},
118    {error,
119     [{structured_error,{M,2},asn1ct_check,
120       {illegal_class_name,'LowerCase'}},
121      {structured_error,{M,3},asn1ct_check,
122       {unique_and_default,id}}
123     ]} = run(P, Config),
124    ok.
125
126constraints(Config) ->
127    M = 'Constraints',
128    P = {M,
129	 <<"Constraints DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
130	   "  II-1 ::= INTEGER (holder-1.&obj)\n"
131	   "  II-2 ::= INTEGER ('1234'H<..20)\n"
132	   "  II-3 ::= INTEGER (1..<\"abc\")\n"
133	   "  II-4 ::= INTEGER (10..1)\n"
134
135	   "  HOLDER ::= CLASS {\n"
136	   "    &obj HOLDER OPTIONAL\n"
137	   "  }\n"
138
139	   "  holder-1 HOLDER ::= { &obj holder-2 }\n"
140	   "  holder-2 HOLDER ::= { }\n"
141	   "END\n">>},
142    {error,
143     [
144      {structured_error,{M,2},asn1ct_check,illegal_value},
145      {structured_error,{M,3},asn1ct_check,illegal_integer_value},
146      {structured_error,{M,4},asn1ct_check,illegal_integer_value},
147      {structured_error,{M,5},asn1ct_check,reversed_range}
148     ]} = run(P, Config),
149    ok.
150
151enumerated(Config) ->
152    M = 'Enumerated',
153    P = {M,
154	 <<"Enumerated DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
155	   "  Enum ::= ENUMERATED { a, b, c }\n"
156	   "  e Enum ::= d\n"
157	   "  EnumExt ::= ENUMERATED { x, ..., y }\n"
158	   "  ext EnumExt ::= z\n"
159	   "  S1 ::= SEQUENCE {\n"
160           "    ge1 Enum DEFAULT a,\n"
161           "    ge2 EnumExt DEFAULT x,\n"
162           "    ge3 EnumExt DEFAULT y,\n"
163	   "    e Enum DEFAULT aa\n"
164           "  }\n"
165	   "  S2 ::= SEQUENCE {\n"
166	   "    e2 EnumExt DEFAULT xyz\n"
167	   "  }\n"
168
169	   "  BadEnum1 ::= ENUMERATED {a, b, c, b }\n"
170	   "  BadEnum2 ::= ENUMERATED {a(1), b(2), b(3) }\n"
171	   "  BadEnum3 ::= ENUMERATED {a(1), b(1) }\n"
172	   "  BadEnum4 ::= ENUMERATED {a, b, ..., c(0) }\n"
173	   "  BadEnum5 ::= ENUMERATED {a, b, ..., c(10), d(5) }\n"
174	   "END\n">>},
175    {error,
176     [
177      {structured_error,{M,3},asn1ct_check,{undefined,d}},
178      {structured_error,{M,5},asn1ct_check,{undefined,z}},
179      {structured_error,{M,6},asn1ct_check,{undefined,aa}},
180      {structured_error,{M,12},asn1ct_check,{undefined,xyz}},
181      {structured_error,{M,15},asn1ct_check,
182       {enum_illegal_redefinition,b}},
183      {structured_error,{M,16},asn1ct_check,
184       {enum_illegal_redefinition,b}},
185      {structured_error,{M,17},asn1ct_check,
186       {enum_reused_value,b,1}},
187      {structured_error,{M,18},asn1ct_check,
188       {enum_reused_value,c,0}},
189      {structured_error,{M,19},asn1ct_check,
190       {enum_not_ascending,d,5,10}}
191     ]
192    } = run(P, Config),
193    ok.
194
195imports_exports(Config) ->
196    Ext = 'ExternalModule',
197    ExtP = {Ext,
198	    <<"ExternalModule DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
199	      "IMPORTS\n"
200	      " Int, NonExistingImport FROM ImportsFrom;\n"
201
202	      " Existing ::= INTEGER\n"
203	      "END\n">>},
204    {error,
205     [{structured_error,
206       {Ext,3},
207       asn1ct_check,
208       {undefined_import,'NonExistingImport',
209	'ImportsFrom'}}]} = run(ExtP, Config),
210
211    M = 'Imports',
212    P = {M,
213	 <<"Imports DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
214	   "EXPORTS\n"
215	   " T, UndefinedType;\n"
216
217	   "IMPORTS\n"
218	   " NotDefined, Existing, Int, NonExistingImport\n"
219	   "   FROM ExternalModule\n"
220	   " X FROM UndefinedModule objid\n"
221	   " Y, Z FROM UndefinedModule2;\n"
222
223	   "objid OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) remote-operations(4)\n"
224	   "    notation(0)}\n"
225	   "T ::= INTEGER\n"
226	   "END\n">>},
227    {error,[{structured_error,{M,3},asn1ct_check,
228	     {undefined_export, 'UndefinedType'}},
229	    {structured_error,{M,5},asn1ct_check,
230	     {undefined_import,'NonExistingImport',Ext}},
231	    {structured_error,{M,5},asn1ct_check,
232	     {undefined_import,'NotDefined',Ext}},
233	    {structured_error,{M,7},asn1ct_check,
234	     {undefined_import,'X','UndefinedModule'}},
235	    {structured_error,{M,8},asn1ct_check,
236	     {undefined_import,'Y','UndefinedModule2'}},
237	    {structured_error,{M,8},asn1ct_check,
238	     {undefined_import,'Z','UndefinedModule2'}}
239	   ]} = run(P, Config),
240    ok.
241
242instance_of(Config) ->
243    M = 'InstanceOf',
244    P = {M,
245	 <<"InstanceOf DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
246	   "XX ::= INSTANCE OF CL ({TI})\n"
247	   "CL ::= CLASS {\n"
248           "&id INTEGER,\n"
249           "&Type\n"
250	   "}\n"
251	   "o1 CL ::= {&id 1, &Type OCTET STRING}\n"
252	   "TI CL ::= { o1 }\n"
253	   "END\n">>},
254    {error,
255     [{structured_error,{M,2},asn1ct_check,{illegal_instance_of,'CL'}}
256     ]} = run(P, Config),
257    ok.
258
259integers(Config) ->
260    M = 'Integers',
261    P = {M,
262	 <<"Integers DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
263	   "  Int1 ::= INTEGER {a(1), a(1)}\n"
264	   "  Int2 ::= INTEGER {a(1), b(2), a(3)}\n"
265	   "  Int3 ::= INTEGER {x(1), y(1)}\n"
266	   "  i0 INTEGER ::= 1\n"
267	   "  Int4 ::= INTEGER {x(i0), y(undef) }\n"
268	   "END\n">>},
269    {error,
270     [{structured_error,{M,2},asn1ct_check,{namelist_redefinition,a}},
271      {structured_error,{M,3},asn1ct_check,{namelist_redefinition,a}},
272      {structured_error,{M,4},asn1ct_check,{value_reused,1}},
273      {structured_error,{M,6},asn1ct_check,{undefined,undef}}
274     ]} = run(P, Config),
275    ok.
276
277
278objects(Config) ->
279    M = 'Objects',
280    P = {M,
281	 <<"Objects DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
282	   "  obj1 CL ::= { &wrong 42 }\n"
283	   "  obj2 CL ::= { &wrong 1, &Wrong INTEGER }\n"
284	   "  obj3 CL ::= { &Data OCTET STRING }\n"
285	   "  obj4 SMALL ::= { &code 42 }\n"
286	   "  InvalidSet CL ::= { obj1 }\n"
287	   "  obj5 CL ::= {}\n"
288	   "  ErrSet ::= PT{ {PT{inst}}}\n"
289	   "  obj6 CL ::= 7\n"
290	   "  obj7 CL ::= int\n"
291	   "  obj8 NON-CLASS ::= { &id 1 }\n"
292
293	   "  CL ::= CLASS {\n"
294	   "    &code INTEGER UNIQUE,\n"
295	   "    &enum ENUMERATED { a, b, c},\n"
296	   "    &Data,\n"
297	   "    &object CL,\n"
298	   "    &Set CL,\n"
299	   "    &vartypevalue &Data,\n"
300	   "    &VarTypeValue &Data\n"
301	   "  }\n"
302
303	   "  SMALL ::= CLASS {\n"
304	   "    &code INTEGER UNIQUE,\n"
305           "    &i INTEGER\n"
306           "  }\n"
307
308	   "  PT{SMALL:Small} ::= SEQUENCE { a SMALL.&code ({Small}) }\n"
309	   "  inst SMALL ::= {&code 42, &i 4711}\n"
310
311	   "  int INTEGER ::= 42\n"
312	   "  NON-CLASS ::= SEQUENCE { a BOOLEAN }\n"
313	   "END\n">>},
314    {error,
315     [
316      {structured_error,{M,2},asn1ct_check,
317       {invalid_fields,[wrong],obj1}},
318      {structured_error,{M,3},asn1ct_check,
319       {invalid_fields,['Wrong',wrong],obj2}},
320      {structured_error,{M,4},asn1ct_check,
321       {missing_mandatory_fields,['Set','VarTypeValue',code,
322				  enum,object,vartypevalue],obj3}},
323      {structured_error,{M,5},asn1ct_check,
324       {missing_mandatory_fields,[i],obj4}},
325      {structured_error,{M,6},asn1ct_check,
326       {invalid_fields,[wrong],'InvalidSet'}},
327      {structured_error,{M,7},asn1ct_check,
328       {missing_mandatory_fields,
329	['Data','Set','VarTypeValue',code,enum,object,
330	 vartypevalue],obj5}},
331      {structured_error,{M,8},asn1ct_check,invalid_objectset},
332      {structured_error,{M,9},asn1ct_check,illegal_object},
333      {structured_error,{M,10},asn1ct_check,illegal_object},
334      {structured_error,{M,11},asn1ct_check,illegal_object}
335     ]
336    } = run(P, Config),
337    ok.
338
339object_field_extraction(Config) ->
340    M = 'ObjectFieldExtraction',
341    P = {M,
342	 <<"ObjectFieldExtraction DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
343
344	   "  DataObjSet DATA-CLASS ::= {\n"
345	   "    holder-object-1.&int,\n"
346	   "    ...\n"
347	   "  }\n"
348
349	   "  DataObjSetNoExt DATA-CLASS ::= {\n"
350	   "    holder-object-1.&int\n"
351	   "  }\n"
352
353	   "  holder-object-1 HOLDER-CLASS ::= {\n"
354	   "    &int 42\n"
355	   "  }\n"
356
357	   "  HOLDER-CLASS ::= CLASS {\n"
358           "    &int INTEGER\n"
359           "  }\n"
360
361	   "  DATA-CLASS ::= CLASS {\n"
362           "    &id INTEGER\n"
363           "  }\n"
364
365	   "END\n">>},
366    {error,
367     [
368      {structured_error,{M,2},asn1ct_check,illegal_object},
369      {structured_error,{M,6},asn1ct_check,illegal_object}
370     ]
371    } = run(P, Config),
372    ok.
373
374object_sets(Config) ->
375    M = 'ObjectSets',
376    P = {M, <<"ObjectSets DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
377	      "TEST-UNIQ ::= CLASS { &id INTEGER UNIQUE,  &test INTEGER }\n"
378	      "UniqSet TEST-UNIQ ::= { { &id 1, &test 1 } | {&id 1, &test 2} }\n"
379
380	      "DOUBLE-UNIQ ::= CLASS { &id1 INTEGER UNIQUE,"
381              "           &id INTEGER UNIQUE }\n"
382              "DoubleSet DOUBLE-UNIQ ::= { {&id1 1, &id2 2} }\n"
383	      "END\n">>},
384    {error,
385     [{structured_error,{M,3},asn1ct_check,{non_unique_object,1}},
386      {structured_error,{M,5},asn1ct_check,multiple_uniqs}
387     ]
388    } = run(P, Config),
389    ok.
390
391oids(Config) ->
392    M = 'OIDS',
393    P = {M,<<"OIDS DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
394	    "CONTAINER ::= CLASS { &id OBJECT IDENTIFIER UNIQUE,\n"
395	    "                      &int INTEGER OPTIONAL,\n"
396	    "                      &seq SEQUENCE { a INTEGER } OPTIONAL\n"
397	    "}\n"
398
399	    "-- This is line 6.\n"
400	    "object-1 CONTAINER ::= { &id {1 2 3}, &int 42 }\n"
401	    "object-2 CONTAINER ::= { &id {1 999}, &int 0 }\n"
402	    "object-3 CONTAINER ::= { &id {1 2}, &seq { a 42 } }\n"
403	    "oid-1 OBJECT IDENTIFIER ::= object-1.&int\n"
404	    "oid-2 OBJECT IDENTIFIER ::= object-2.&id\n"
405	    "oid-3 OBJECT IDENTIFIER ::= object-3.&seq\n"
406	    "-- This is line 13.\n"
407
408	    "oid-5 OBJECT IDENTIFIER ::= { a 42, b 19 }\n"
409
410	    "oid-6 OBJECT IDENTIFIER ::= int\n"
411	    "int INTEGER ::= 42\n"
412
413	    "oid-7 OBJECT IDENTIFIER ::= seq\n"
414	    "seq SEQUENCE { x INTEGER } ::= { x 11 }\n"
415
416	    "oid-8 OBJECT IDENTIFIER ::= os\n"
417	    "os OCTET STRING ::= '1234'H\n"
418
419	    "oid-9 OBJECT IDENTIFIER ::= { 1 os }\n"
420
421	    "oid-10 OBJECT IDENTIFIER ::= { 1 invalid }\n"
422
423	    "-- This is line 23.\n"
424	    "oid-11 OBJECT IDENTIFIER ::= { 0 legal-oid }\n"
425	    "legal-oid OBJECT IDENTIFIER ::= {1 2 3}\n"
426
427	    "bad-root-1 OBJECT IDENTIFIER ::= {99}\n"
428	    "bad-root-2 OBJECT IDENTIFIER ::= {0 42}\n"
429
430	    "oid-object-ref-1 OBJECT IDENTIFIER ::= object-1\n"
431	    "oid-object-ref-2 OBJECT IDENTIFIER ::= { object-1 19 } \n"
432
433	    "oid-int OBJECT IDENTIFIER ::= 42\n"
434	    "oid-sequence OBJECT IDENTIFIER ::= {a 42, b 35}\n"
435
436	     "END\n">>},
437    {error,
438     [
439      {structured_error,{M,8},asn1ct_check,{illegal_oid,o_id}},
440      {structured_error,{M,10},asn1ct_check,{illegal_oid,o_id}},
441      {structured_error,{M,11},asn1ct_check,{illegal_oid,o_id}},
442      {structured_error,{M,12},asn1ct_check,{illegal_oid,o_id}},
443      {structured_error,{M,14},asn1ct_check,{illegal_oid,o_id}},
444      {structured_error,{M,15},asn1ct_check,{illegal_oid,o_id}},
445      {structured_error,{M,17},asn1ct_check,{illegal_oid,o_id}},
446      {structured_error,{M,19},asn1ct_check,{illegal_oid,o_id}},
447      {structured_error,{M,21},asn1ct_check,{illegal_oid,o_id}},
448      {structured_error,{M,22},asn1ct_check,{illegal_oid,o_id}},
449      {structured_error,{M,24},asn1ct_check,{illegal_oid,o_id}},
450      {structured_error,{M,26},asn1ct_check,{illegal_oid,o_id}},
451      {structured_error,{M,27},asn1ct_check,{illegal_oid,o_id}},
452      {structured_error,{M,28},asn1ct_check,{illegal_oid,o_id}},
453      {structured_error,{M,29},asn1ct_check,{illegal_oid,o_id}},
454      {structured_error,{M,30},asn1ct_check,{illegal_oid,o_id}},
455      {structured_error,{M,31},asn1ct_check,{illegal_oid,o_id}}
456     ]
457    } = run(P, Config),
458    ok.
459
460rel_oids(Config) ->
461    M = 'REL-OIDS',
462    P = {M,<<"REL-OIDS DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
463	     "legal-oid OBJECT IDENTIFIER ::= {1 2}\n"
464	     "legal-roid RELATIVE-OID ::= {1 2}\n"
465	     "CONTAINER ::= CLASS { &oid OBJECT IDENTIFIER OPTIONAL,\n"
466	     "                      &int INTEGER OPTIONAL,\n"
467	     "                      &seq SEQUENCE { a INTEGER } OPTIONAL\n"
468	     "}\n"
469	     "object-1 CONTAINER ::= { &oid {1 2 3},\n"
470	     "                         &int 42,\n",
471	     "                         &seq {a 42}\n"
472	     "                       }\n"
473
474	     "wrong-type-rel-oid-1 RELATIVE-OID ::= legal-oid\n"
475	     "wrong-type-rel-oid-2 RELATIVE-OID ::= object-1.&oid\n"
476	     "wrong-type-rel-oid-3 RELATIVE-OID ::= object-1.&int\n"
477	     "wrong-type-rel-oid-4 RELATIVE-OID ::= object-1.&seq\n"
478	     "wrong-type-rel-oid-5 RELATIVE-OID ::= object-1.&undef\n"
479
480	     "oid-bad-first OBJECT IDENTIFIER ::= {legal-roid 3}\n"
481	     "END\n">>},
482    {error,
483     [
484      {structured_error,{M,12},asn1ct_check,{illegal_oid,rel_oid}},
485      {structured_error,{M,13},asn1ct_check,{illegal_oid,rel_oid}},
486      {structured_error,{M,14},asn1ct_check,{illegal_oid,rel_oid}},
487      {structured_error,{M,15},asn1ct_check,{illegal_oid,rel_oid}},
488      {structured_error,{M,16},asn1ct_check,{undefined_field,undef}},
489      {structured_error,{M,17},asn1ct_check,{illegal_oid,o_id}}
490     ]
491    } = run(P, Config),
492    ok.
493
494
495parameterization(Config) ->
496    M = 'Parameterization',
497    P = {M,
498	 <<"Parameterization DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
499	   "  NotUppercase{lowercase} ::= INTEGER (lowercase)\n"
500
501	   "  P{T1,T2} ::= SEQUENCE { a T1, b T2 }\n"
502	   "  S ::= P{OCTET STRING}\n"
503
504	   "  Seq ::= SEQUENCE { a INTEGER }\n"
505	   "  Sbad ::= Seq{INTEGER}\n"
506
507	   "END\n">>},
508    {error,
509     [{structured_error,{M,2},asn1ct_check,
510       {illegal_typereference,lowercase}},
511      {structured_error,{M,4},asn1ct_check,
512       param_wrong_number_of_arguments},
513      {structured_error,{M,6},asn1ct_check,
514       {param_bad_type, 'Seq'}}
515     ]
516    } = run(P, Config),
517    ok.
518
519
520constructed(Config) ->
521    M = 'Const',
522    P = {M,
523	 <<"Const DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
524	   "  Seq1 ::= SEQUENCE {a INTEGER, b BIT STRING, a BOOLEAN}\n"
525	   "  Ch   ::= CHOICE {a INTEGER, b BIT STRING, a BOOLEAN}\n"
526	   "  Seq2 ::= SEQUENCE {COMPONENTS OF Ch}\n"
527	   "  CL   ::= CLASS { &id INTEGER UNIQUE, &Type }\n"
528	   "  Seq3 ::= SEQUENCE { id CL.&id, d CL.&foo }\n"
529
530	   "  Seq4 ::= SEQUENCE { a INTEGER, z INTEGER OPTIONAL, b Set1 }\n"
531	   "  Set1 ::= SET { c BOOLEAN, d INTEGER }\n"
532	   "  s1 Seq4 ::= {a 42, b {c TRUE, zz 4711}}\n"
533	   "  s2 Seq4 ::= {a 42, b {c TRUE, d FALSE}}\n"
534	   "  s3 Seq4 ::= {a 42, b {c TRUE}}\n"
535	   "  s4 Seq4 ::= {a 42, b {c TRUE, d 4711}, zz 4712}\n"
536	   "  s5 Seq4 ::= {a 42}\n"
537	   "  s6 Seq4 ::= {a 42, zz 4712, b {c TRUE, d 4711}}\n"
538	   "END\n">>},
539    {error,
540     [{structured_error,{M,2},asn1ct_check,{duplicate_identifier,a}},
541      {structured_error,{M,3},asn1ct_check,{duplicate_identifier,a}},
542      {structured_error,{M,4},asn1ct_check,{illegal_COMPONENTS_OF,'Ch'}},
543      {structured_error,{M,6},asn1ct_check,{illegal_object_field,foo}},
544
545      {structured_error,{M,9},asn1ct_check,{illegal_id,zz}},
546      {structured_error,{M,10},asn1ct_check,illegal_integer_value},
547      {structured_error,{M,11},asn1ct_check,{missing_id,d}},
548      {structured_error,{M,12},asn1ct_check,{illegal_id,zz}},
549      {structured_error,{M,13},asn1ct_check,{missing_id,b}},
550      {structured_error,{M,14},asn1ct_check,{illegal_id,zz}}
551     ]
552    } = run(P, Config),
553    ok.
554
555syntax(Config) ->
556    M = 'Syntax',
557    P = {M,
558	 <<"Syntax DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
559	   "  obj1  CL ::= { WRONG }\n"
560	   "  obj2  CL ::= { CODE 42 AGAIN WRONG }\n"
561	   "  obj3  CL ::= { INTEGER }\n"
562	   "  obj4  CL ::= { BIT STRING }\n"
563	   "  obj5  CL ::= { , }\n"
564	   "  obj6  CL ::= { CODE , }\n"
565	   "  obj7  CL ::= { CODE \"abc\" }\n"
566	   "  obj8  CL ::= { CODE }\n"
567	   "  obj9  CL ::= { CODE 42 ENUM}\n"
568	   "  obj10 CL ::= { CODE 42 ENUM BIT STRING}\n"
569
570	   "  obj11 CL ::= { CODE 42 TYPE 13}\n"
571	   "  obj12 CL ::= { CODE 42 TYPE d}\n"
572	   "  obj13 CL ::= { CODE 42 TYPE bs-value}\n"
573
574	   "  bad-syntax-1 BAD-SYNTAX-1 ::= { BAD 42 }\n"
575
576	   "  obj14 CL ::= { CODE 42 OBJ-SET integer }\n"
577	   "  obj15 CL ::= { CODE 42 OBJ-SET { A B } }\n"
578	   "  obj16 CL ::= { CODE 42 OBJ-SET SEQUENCE { an INTEGER } }\n"
579
580	   "  obj17 CL ::= { CODE 42 OID {seqtag 42} }\n"
581	   "  obj18 CL ::= { CODE 42 OID {seqtag 42, seqtag-again 43} }\n"
582	   "  obj19 CL ::= { CODE 42 OID {one 1 two 2} }\n"
583
584	   "  BAD-SYNTAX-1 ::= CLASS {\n"
585	   "    &code INTEGER UNIQUE\n"
586	   "  } WITH SYNTAX {\n"
587	   "    BAD &bad\n"
588	   "  }\n"
589
590	   "  BAD-SYNTAX-2 ::= CLASS {\n"
591	   "    &code INTEGER UNIQUE\n"
592	   "  } WITH SYNTAX {\n"
593	   "    BAD &Bad\n"
594	   "  }\n"
595
596	   "  BAD-SYNTAX-3 ::= CLASS {\n"
597	   "    &code INTEGER UNIQUE\n"
598	   "  } WITH SYNTAX {\n"
599	   "    [ID &code]\n"
600	   "  }\n"
601
602	   "  BAD-SYNTAX-4 ::= CLASS {\n"
603	   "    &code INTEGER UNIQUE\n"
604	   "  } WITH SYNTAX {\n"
605	   "    ID\n"
606	   "  }\n"
607
608	   "  BAD-SYNTAX-5 ::= CLASS {\n"
609	   "    &code INTEGER UNIQUE,\n"
610	   "    &Type\n"
611	   "  } WITH SYNTAX {\n"
612	   "    ID\n"
613	   "  }\n"
614
615	   "  BAD-SYNTAX-6 ::= CLASS {\n"
616	   "    &code INTEGER UNIQUE\n"
617	   "  } WITH SYNTAX {\n"
618	   "    ID &code, &code\n"
619	   "  }\n"
620
621	   "  BAD-SYNTAX-7 ::= CLASS {\n"
622	   "    &code INTEGER UNIQUE,\n"
623	   "    &Type\n"
624	   "  } WITH SYNTAX {\n"
625	   "    ID &Type, &code, &code, &Type\n"
626	   "  }\n"
627
628	   "  CL ::= CLASS {\n"
629	   "    &code INTEGER UNIQUE,\n"
630	   "    &enum ENUMERATED { a, b, c} OPTIONAL,\n"
631	   "    &Type OPTIONAL,\n"
632	   "    &ObjSet CL OPTIONAL,\n"
633	   "    &oid OBJECT IDENTIFIER OPTIONAL\n"
634	   "  } WITH SYNTAX {\n"
635	   "    CODE &code [ENUM &enum] [TYPE &Type] [OBJ-SET &ObjSet]\n"
636           "    [OID &oid]\n"
637	   "  }\n"
638
639	   "  bs-value BIT STRING ::= '1011'B\n"
640
641	   "  integer INTEGER ::= 42\n"
642	   "END\n">>},
643    {error,
644     [
645      {structured_error,{M,2},asn1ct_check,
646       {syntax_nomatch,"WRONG"}},
647      {structured_error,{M,3},asn1ct_check,
648       {syntax_nomatch,"AGAIN"}},
649      {structured_error,{M,4},asn1ct_check,
650       {syntax_nomatch,"INTEGER"}},
651      {structured_error,{M,5},asn1ct_check,
652       {syntax_nomatch,"BIT STRING"}},
653      {structured_error,{M,6},asn1ct_check,
654       {syntax_nomatch,"\",\""}},
655      {structured_error,{M,7},asn1ct_check,
656       {syntax_nomatch,"\",\""}},
657      {structured_error,{M,8},asn1ct_check,
658       {syntax_nomatch,"\"abc\""}},
659      {structured_error,{M,9},asn1ct_check,
660       syntax_nomatch},
661      {structured_error,{M,10},asn1ct_check,
662       syntax_nomatch},
663      {structured_error,{M,11},asn1ct_check,
664       {syntax_nomatch,"BIT STRING"}},
665      {structured_error,{M,12},asn1ct_check,
666       {syntax_nomatch,"13"}},
667      {structured_error,{M,13},asn1ct_check,
668       {syntax_nomatch,"d"}},
669      {structured_error,{M,14},asn1ct_check,
670       {syntax_nomatch,"bs-value"}},
671      {structured_error,{M,15},asn1ct_check,
672       {syntax_undefined_field,bad}},
673      {structured_error,{M,16},asn1ct_check,
674       {syntax_nomatch,"integer"}},
675      {structured_error,{M,17},asn1ct_check,
676       {syntax_nomatch,"\"A B\""}},
677      {structured_error,{M,18},asn1ct_check,
678       {syntax_nomatch,"SEQUENCE"}},
679      {structured_error,{M,19},asn1ct_check,
680       {syntax_nomatch,"\"seqtag 42\""}},
681      {structured_error,{M,20},asn1ct_check,
682       {syntax_nomatch,"\"seqtag 42 seqtag-again 43\""}},
683      {structured_error,{M,21},asn1ct_check,
684       {syntax_nomatch,"\"one 1 two 2\""}},
685      {structured_error,{M,22},asn1ct_check,
686       {syntax_undefined_field,bad}},
687      {structured_error,{M,27},asn1ct_check,
688       {syntax_undefined_field,'Bad'}},
689      {structured_error,{M,32},asn1ct_check,
690       {syntax_mandatory_in_optional_group,code}},
691      {structured_error,{M,37},asn1ct_check,
692       {syntax_missing_mandatory_fields,[code]}},
693      {structured_error,{M,42},asn1ct_check,
694       {syntax_missing_mandatory_fields,['Type',code]}},
695      {structured_error,{M,48},asn1ct_check,
696       {syntax_duplicated_fields,[code]}},
697      {structured_error,{M,53},asn1ct_check,
698       {syntax_duplicated_fields,['Type',code]}}
699     ]
700    } = run(P, Config),
701    ok.
702
703table_constraints(Config) ->
704    M = 'TableConstraints',
705    P = {M,
706	 <<"TableConstraints DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
707	   "  Seq-1 ::= SEQUENCE {\n"
708	   "    contentType CONTENTS.&id,\n"
709	   "    content CONTENTS.&Type({Contents}{@contentType})\n"
710	   "  }\n"
711
712	   "  Seq-2 ::= SEQUENCE {\n"
713	   "    contentType INTEGER,\n"
714	   "    content CONTENTS.&Type({Contents}{@contentType})\n"
715	   "  }\n"
716
717	   "  Int ::= INTEGER ({1})\n"
718
719	   "  Seq-3 ::= SEQUENCE {\n"
720	   "    contentType CONTENTS.&id({1})\n"
721	   "  }\n"
722
723	   "Contents CONTENTS ::= {\n"
724	   "  {OCTET STRING IDENTIFIED BY {2 1 1}}\n"
725	   "}\n"
726
727	   "CONTENTS ::= TYPE-IDENTIFIER\n"
728	   "END\n">>},
729    {error,
730     [{structured_error,
731       {M,2},asn1ct_check,
732       {missing_table_constraint,contentType}},
733      {structured_error,
734       {M,6},asn1ct_check,
735       {missing_ocft,contentType}},
736      {structured_error,
737       {M,10},asn1ct_check,
738       illegal_table_constraint},
739      {structured_error,
740       {M,11},asn1ct_check,
741       invalid_table_constraint}
742     ]} = run(P, Config),
743    ok.
744
745tags(Config) ->
746    M = 'Tags',
747    P = {M,
748	 <<"Tags DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
749	   "SeqOpt1 ::= SEQUENCE\n"
750	   "{\n"
751	   "bool1  BOOLEAN OPTIONAL,\n"
752	   "int1  INTEGER,\n"
753	   "seq1  SeqIn OPTIONAL\n"
754	   "}\n"
755
756	   "SeqOpt1Imp ::= SEQUENCE \n"
757	   "{\n"
758	   "bool1 [1] BOOLEAN OPTIONAL,\n"
759	   "int1  INTEGER,\n"
760	   "seq1  [2] SeqIn OPTIONAL,\n"
761	   "seq2  [2] SeqIn OPTIONAL,\n"
762	   "...,\n"
763	   "int2  [3] SeqIn,\n"
764	   "int3  [3] SeqIn\n"
765	   "}\n"
766
767	   "SeqIn ::= SEQUENCE \n"
768	   "{\n"
769	   "boolIn  BOOLEAN,\n"
770	   "intIn  INTEGER\n"
771	   "}\n"
772	   "\n"
773
774
775	   "Set1 ::= SET {\n"
776	   " os [0] OCTET STRING,\n"
777	   " bool [0] BOOLEAN\n"
778	   "}\n"
779
780	   "Seq1 ::= SEQUENCE {\n"
781	   "a [0] IMPLICIT Choice OPTIONAL\n"
782	   "}\n"
783	   "Seq2 ::= SEQUENCE {\n"
784	   "a [0] IMPLICIT ANY OPTIONAL\n"
785	   "}\n"
786	   "Choice ::=\n"
787	   "CHOICE {\n"
788	   "a [0] BOOLEAN,\n"
789	   "b [1] INTEGER\n"
790	   "}\n"
791
792	   "END\n">>},
793    {error,
794     [{structured_error,
795       {M,8},asn1ct_check,
796       {duplicate_tags,[seq1,seq2]}},
797      {structured_error,
798       {M,24},asn1ct_check,
799       {duplicate_tags,[bool,os]}},
800      {structured_error,
801       {M,28},asn1ct_check,
802       {implicit_tag_before,choice}},
803      {structured_error,
804       {M,31},asn1ct_check,
805       {implicit_tag_before,open_type}}
806     ]} = run(P, Config),
807    ok.
808
809
810values(Config) ->
811    M = 'Values',
812    P = {M,
813	 <<"Values DEFINITIONS AUTOMATIC TAGS ::= BEGIN\n"
814	   "  os1 OCTET STRING ::= \"abc\"\n"
815	   "  os2 OCTET STRING ::= 42\n"
816	   "  os3 OCTET STRING ::= { 1, 3 }\n"
817	   "  os4 OCTET STRING ::= '1234'H\n"
818	   "  Seq ::= SEQUENCE {\n"
819	   "    an OCTET STRING\n"
820	   "  }\n"
821	   "  seq Seq ::= { an int }\n"
822	   "  os5 OCTET STRING ::= holder-1.&str\n"
823	   "  os6 OCTET STRING ::= int\n"
824
825	   "  int1 INTEGER ::= \"string\"\n"
826	   "  int2 INTEGER ::= os4\n"
827	   "  int3 INTEGER ::= not-defined\n"
828	   "  int4 INTEGER ::= holder-1.&str\n"
829	   "  int5 INTEGER ::= holder-2.&obj\n"
830	   "  int6 INTEGER ::= holder-2.&undefined-field\n"
831	   "  int7 INTEGER ::= holder-2.&UndefinedField.&id\n"
832
833	   "  bs1 BIT STRING ::= 42\n"
834	   "  bs2 BIT STRING ::= {a,b}\n"
835	   "  bs3 BIT STRING {a(0),z(25)} ::= {a,b}\n"
836	   "  bs4 BIT STRING {a(0),z(25)} ::= int\n"
837	   "  bs5 BIT STRING ::= holder-2.&str\n"
838	   "  bs6 BIT STRING ::= holder-2.&obj\n"
839
840	   "  b1 BOOLEAN ::= 42\n"
841	   "  b2 BOOLEAN ::= {a,b}\n"
842
843	   "  HOLDER ::= CLASS {\n"
844	   "    &str IA5String,\n"
845	   "    &obj HOLDER OPTIONAL\n"
846	   "  }\n"
847
848	   "  holder-1 HOLDER ::= { &str \"xyz\" }\n"
849	   "  holder-2 HOLDER ::= { &str \"xyz\", &obj holder-1 }\n"
850
851	   "  ext-1 EXTERNAL ::= {identification bad:{1 2 3}, data-value '123'H}\n"
852	   "  ext-2 EXTERNAL ::= {identification syntax:{1 2 3}, data '123'H}\n"
853
854	   "  CH ::= CHOICE { a INTEGER, b BOOLEAN }\n"
855	   "  ch1 CH ::= 2344\n"
856	   "  ch2 CH ::= zz:34\n"
857
858	   "  st1 an < Seq ::= 42\n"
859	   "  st2 zz < CH ::= 42\n"
860	   "  st3 a < HOLDER ::= 42\n"
861	   "  st4 a < INTEGER ::= 42\n"
862
863	   "  int INTEGER ::= 42\n"
864	   "END\n">>},
865    {error,
866     [
867      {structured_error,{M,2},asn1ct_check,
868       illegal_octet_string_value},
869      {structured_error,{M,3},asn1ct_check,
870       illegal_octet_string_value},
871      {structured_error,{M,4},asn1ct_check,
872       illegal_octet_string_value},
873      {structured_error,{M,9},asn1ct_check,
874       illegal_octet_string_value},
875      {structured_error,{M,10},asn1ct_check,
876       illegal_octet_string_value},
877      {structured_error,{M,11},asn1ct_check,
878       illegal_octet_string_value},
879      {structured_error,{M,12},asn1ct_check,
880       illegal_integer_value},
881      {structured_error,{M,13},asn1ct_check,
882       illegal_integer_value},
883      {structured_error,{M,14},asn1ct_check,
884       illegal_integer_value},
885      {structured_error,{M,15},asn1ct_check,
886       illegal_integer_value},
887      {structured_error,{M,16},asn1ct_check,
888       illegal_integer_value},
889      {structured_error,{M,17},asn1ct_check,
890       {undefined_field,'undefined-field'}},
891      {structured_error,{M,18},asn1ct_check,
892       {undefined_field,'UndefinedField'}},
893      {structured_error,{M,19},asn1ct_check,
894       {illegal_value, "BIT STRING"}},
895      {structured_error,{M,20},asn1ct_check,
896       {illegal_value, "BIT STRING"}},
897      {structured_error,{M,21},asn1ct_check,
898       {illegal_value, "BIT STRING"}},
899      {structured_error,{M,22},asn1ct_check,
900       {illegal_value, "BIT STRING"}},
901      {structured_error,{M,23},asn1ct_check,
902       {illegal_value, "BIT STRING"}},
903      {structured_error,{M,24},asn1ct_check,
904       {illegal_value, "BIT STRING"}},
905      {structured_error,{M,25},asn1ct_check,
906       {illegal_value, "BOOLEAN"}},
907      {structured_error,{M,26},asn1ct_check,
908       {illegal_value, "BOOLEAN"}},
909      {structured_error,{M,33},asn1ct_check,
910       illegal_external_value},
911      {structured_error,{M,34},asn1ct_check,
912       illegal_external_value},
913      {structured_error,{M,36},asn1ct_check,
914       {illegal_id, 2344}},
915      {structured_error,{M,37},asn1ct_check,
916       {illegal_id, zz}},
917      {structured_error,{M,38},asn1ct_check,
918       {illegal_choice_type, 'Seq'}},
919      {structured_error,{M,39},asn1ct_check,
920       {illegal_id, zz}},
921      {structured_error,{M,40},asn1ct_check,
922       {illegal_choice_type, 'HOLDER'}},
923      {structured_error,{M,41},asn1ct_check,
924       {illegal_choice_type, 'INTEGER'}}
925     ]
926    } = run(P, Config),
927    ok.
928
929
930run({Mod,Spec}, Config) ->
931    Base = atom_to_list(Mod) ++ ".asn1",
932    File = filename:join(proplists:get_value(priv_dir, Config), Base),
933    Include0 = filename:dirname(proplists:get_value(data_dir, Config)),
934    Include = filename:join(filename:dirname(Include0), "asn1_SUITE_data"),
935    ok = file:write_file(File, Spec),
936    asn1ct:compile(File, [{i, Include}]).
937