1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2014-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(syntax_SUITE). 22-export([suite/0,all/0,groups/0, 23 assignment/1, 24 class/1, 25 constraints/1, 26 exports/1, 27 header/1, 28 imports/1, 29 objects/1, 30 sequence/1, 31 syntax/1, 32 tokenizer/1, 33 types/1, 34 values/1]). 35 36-include_lib("common_test/include/ct.hrl"). 37 38suite() -> [{ct_hooks, [ts_install_cth]}]. 39 40all() -> 41 [{group,p}]. 42 43groups() -> 44 [{p,parallel(), 45 [assignment, 46 class, 47 constraints, 48 exports, 49 header, 50 imports, 51 objects, 52 sequence, 53 syntax, 54 tokenizer, 55 types, 56 values]}]. 57 58parallel() -> 59 case erlang:system_info(schedulers) > 1 of 60 true -> [parallel]; 61 false -> [] 62 end. 63 64assignment(Config) -> 65 Head = "Assignment DEFINITIONS AUTOMATIC TAGS ::=\nBEGIN\n", 66 End = "\nEND\n", 67 L0 = [{"42",3,{syntax_error,42}}, 68 {"i",4,{syntax_error,'END'}}, 69 {"i ::=",3,{syntax_error,'::='}}, 70 {"i type",4,{syntax_error,'END'}}, 71 {"i type ::=",3,{syntax_error,'::='}}, 72 {"i TYPE",4,{syntax_error,'END'}}, 73 {"i TYPE ::= ",4,{syntax_error,'END'}}, 74 {"i INTEGER ::= 42 garbage",4,{syntax_error,'END'}}, 75 {"i{T} Type",4,{syntax_error,'END'}}, 76 {"TYPE",4,{syntax_error,'END'}}, 77 {"TYPE ::=",4,{syntax_error,'END'}}, 78 {"TYPE{ ::=",3,{syntax_error,'::='}}, 79 {"TYPE{P, ::=",3,{syntax_error,'::='}}, 80 {"TYPE{P,} ::=",3,{syntax_error,'}'}}, 81 {"TYPE{Gov:} ::=",3,{syntax_error,':'}}, 82 {"TYPE{A} CL ",4,{syntax_error,'END'}}, 83 {"ObjSet CL",4,{syntax_error,'END'}} 84 ], 85 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 86 run(L, "Assignment", Config), 87 ok. 88 89class(Config) -> 90 Head = "Class DEFINITIONS AUTOMATIC TAGS ::=\n" 91 "BEGIN\n" 92 " CL ::= CLASS {", 93 End = "\nEND\n", 94 L0 = [{"id",3,{syntax_error,'id'}}, 95 {"&id INTEGER",4,{syntax_error,'END'}}, 96 {"&id INTEGER,",4,{syntax_error,'END'}}, 97 {"&id,",3,{syntax_error,','}}, 98 {"&id OPTIONAL",3,{syntax_error,'OPTIONAL'}}, 99 {"&id INTEGER OPTIONAL",4,{syntax_error,'END'}}, 100 {"&var &Field",4,{syntax_error,'END'}}, 101 {"&Type,",4,{syntax_error,'END'}}, 102 {"&Type OPTIONAL",4,{syntax_error,'END'}}, 103 {"&ValueSet INTEGER OPTIONAL",4,{syntax_error,'END'}}, 104 {"&ValueSet INTEGER DEFAULT",4,{syntax_error,'END'}}, 105 {"&ValueSet INTEGER DEFAULT {",4,{syntax_error,'END'}}, 106 {"&ValueSet INTEGER DEFAULT {a",4,{syntax_error,'END'}}, 107 {"&Var &Field",4,{syntax_error,'END'}} 108 ], 109 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 110 run(L, "Class", Config), 111 ok. 112 113constraints(Config) -> 114 Head = "Constraints DEFINITIONS AUTOMATIC TAGS ::=\n" 115 "BEGIN\n" 116 " Type ::= ", 117 End = "\nEND\n", 118 L0 = [{"INTEGER (",4,{syntax_error,'END'}}, 119 {"INTEGER (10x",3,{syntax_error,x}}, 120 {"INTEGER (10|(10y",3,{syntax_error,y}}, 121 {"INTEGER (CONSTRAINED BY {}",4,{syntax_error,'END'}}, 122 {"INTEGER (CONSTRAINED BY {INTEGER garbage",3, 123 {syntax_error,garbage}}, 124 {"INTEGER ({ObjSet",4,{syntax_error,'END'}}, 125 {"INTEGER ({ObjSet}{",3,{syntax_error,'{'}}, 126 {"INTEGER ({ObjSet}{@",3,{syntax_error,'{'}}, 127 {"INTEGER ({ObjSet}{@x",3,{syntax_error,'{'}}, 128 {"INTEGER ({ObjSet}{@x}",4,{syntax_error,'END'}}, 129 {"INTEGER (10 !BOOLEAN",4,{syntax_error,'END'}}, 130 {"INTEGER (10 !BOOLEAN:",4,{syntax_error,'END'}}, 131 {"INTEGER (10 !BOOLEAN:FALSE",4,{syntax_error,'END'}}, 132 {"SEQUENCE {} (WITH COMPONENTS { Type })", 133 3,{syntax_error,'Type'}}, 134 {"SEQUENCE {} (WITH COMPONENTS { x (10)", 135 4,{syntax_error,'END'}}, 136 {"SEQUENCE {} (WITH COMPONENTS { ..., x (10)", 137 4,{syntax_error,'END'}} 138 ], 139 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 140 run(L, "Constraints", Config), 141 ok. 142 143exports(Config) -> 144 Head = "Exports DEFINITIONS AUTOMATIC TAGS ::=\n" 145 "BEGIN\n" 146 " EXPORTS ", 147 End = "\nEND\n", 148 L0 = [{"Type",4,{syntax_error,'END'}} 149 ], 150 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 151 run(L, "Exports", Config), 152 ok. 153 154header(Config) -> 155 L = [{"lowercase",1,{syntax_error,lowercase}}, 156 {"H ",2,{syntax_error,'END-OF-FILE'}}, 157 {"H-",1,{syntax_error,'-'}}, 158 {"42",1,{syntax_error,42}}, 159 {"H definitions",1,{syntax_error,definitions}}, 160 {"H DEFINITIONS STUPID TAGS",1,{syntax_error,'STUPID'}}, 161 {"H DEFINITIONS WHATEVER",1,{syntax_error,'WHATEVER'}}, 162 {"H DEFINITIONS ::= BEGIN",2,{syntax_error,'END-OF-FILE'}}, 163 {"BOOLEAN",1,{syntax_error,'BOOLEAN'}} 164 ], 165 run(L, "H", Config), 166 ok. 167 168imports(Config) -> 169 Head = "Imports DEFINITIONS AUTOMATIC TAGS ::=\n" 170 "BEGIN\n" 171 " IMPORTS ", 172 End = "\nEND\n", 173 L0 = [{"Type FROM X",4,{syntax_error,'END'}}, 174 {"Symbols TO Y",3,{syntax_error,'TO'}} 175 ], 176 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 177 run(L, "Imports", Config), 178 ok. 179 180objects(Config) -> 181 Head = "Objects DEFINITIONS AUTOMATIC TAGS ::=\n" 182 "BEGIN\n" 183 " object CLASS-NAME ::= ", 184 End = "\nEND\n", 185 L0 = [{"{",4,{syntax_error,'END'}}, 186 {"{&min 1, max 10}",3,{syntax_error,max}}, 187 {"{&min 1, Max 10}",3,{syntax_error,'Max'}}, 188 {"{min 1, &max 10}",3,{syntax_error,'&max'}}, 189 {"{min 1, &Max 10}",3,{syntax_error,'&Max'}}, 190 {"{RESERVERD WORD BIT}",3,{syntax_error,'BIT'}}, 191 {"{&min 1",4,{syntax_error,'END'}} 192 ], 193 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 194 run(L, "Objects", Config), 195 ok. 196 197sequence(Config) -> 198 Head = "Sequence DEFINITIONS AUTOMATIC TAGS ::=\n" 199 "BEGIN\n" 200 " Type ::= SEQUENCE {", 201 End = "\nEND\n", 202 L0 = [{"",4,{syntax_error,'END'}}, 203 {" UpperCase",3,{syntax_error,'UpperCase'}}, 204 {" a b",4,{syntax_error,'END'}}, 205 {" i INTEGER",4,{syntax_error,'END'}}, 206 {" ...",4,{syntax_error,'END'}}, 207 {" ..., [[",4,{syntax_error,'END'}}, 208 {" ..., [[ a INTEGER ]",3,{syntax_error,']'}}, 209 {" ..., [[ a INTEGER,",3,{syntax_error,','}}, 210 {" ..., [[ a INTEGER, ... ]]",3,{syntax_error,','}}, 211 {" ... !42 xxx",3,{syntax_error,'xxx'}}, 212 {" ... !42, a INTEGER,",3,{syntax_error,','}} 213 ], 214 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 215 run(L, "Sequence", Config), 216 ok. 217 218syntax(Config) -> 219 Head = "Syntax DEFINITIONS AUTOMATIC TAGS ::=\n" 220 "BEGIN\n" 221 " CL ::= CLASS { &id INTEGER UNIQUE } WITH SYNTAX ", 222 End = "\nEND\n", 223 L0 = [{"{}",3,{syntax_error,'}'}}, 224 {"WORD",3,{syntax_error,'WORD'}}, 225 {"{ Word }",3,{syntax_error,'Word'}}, 226 {"{ [ Word ] }",3,{syntax_error,'Word'}}, 227 {"{ [ WORD }",3,{syntax_error,'}'}}, 228 {"{ WORD;",3,{syntax_error,';'}} 229 ], 230 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 231 run(L, "Syntax", Config), 232 ok. 233 234tokenizer(Config) -> 235 Head = "Tokenize DEFINITIONS AUTOMATIC TAGS ::=\n" 236 "BEGIN\n", 237 End = "\nEND\n", 238 L0 = [{"'",3,eol_in_token}, 239 {"'42'B",3,{invalid_binary_number,"42"}}, 240 {"'ZZZ'H",3,{invalid_hex_number,"ZZZ"}}, 241 {"\"abc",3,missing_quote_at_eof}, 242 {"/*",3,eof_in_comment} 243 ], 244 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 245 run(L, "Tokenizer", Config, asn1ct_tok), 246 ok. 247 248types(Config) -> 249 Head = "Types DEFINITIONS AUTOMATIC TAGS ::=\n" 250 "BEGIN\n" 251 " Type ::= ", 252 End = "\nEND\n", 253 L0 = [{"BIT STRING garbage",4,{syntax_error,'END'}}, 254 {"BIT STRING {",4,{syntax_error,'END'}}, 255 {"BIT STRING { a(42",3,{syntax_error,42}}, 256 {"BIT STRING { a(0)",4,{syntax_error,'END'}}, 257 {"CHOICE {",4,{syntax_error,'END'}}, 258 {"CHOICE { ..., a}",3,{syntax_error,'...'}}, 259 {"CHOICE { UpperCase",3,{syntax_error,'UpperCase'}}, 260 {"CHOICE { i INTEGER",4,{syntax_error,'END'}}, 261 {"CHOICE { ..., i INTEGER }",3,{syntax_error,'...'}}, 262 {"CHOICE { b BOOLEAN, ..., i INTEGER", 263 4,{syntax_error,'END'}}, 264 {"CHOICE { b BOOLEAN, ..., [[ e BOOLEAN, ...]]}", 265 3,{syntax_error,','}}, 266 {"CHOICE { b BOOLEAN, ..., i INTEGER, ..., x BIT STRING}", 267 3,{syntax_error,','}}, 268 {"ENUMERATED {",4,{syntax_error,'END'}}, 269 {"ENUMERATED { 42 }",3,{syntax_error,42}}, 270 {"ENUMERATED { a, b",4,{syntax_error,'END'}}, 271 {"ENUMERATED { a, }",3,{syntax_error,','}}, 272 {"ENUMERATED { a, ...,\nb, ..., c }",4,{syntax_error,','}}, 273 {"INTEGER {",4,{syntax_error,'END'}}, 274 {"INTEGER { a(42)",4,{syntax_error,'END'}}, 275 {"SEQUENCE",3,{syntax_error,'SEQUENCE'}}, 276 %% More tests for SEQUENCE in sequence/1. 277 {"SEQUENCE SIZE (1..10)",4,{syntax_error,'END'}}, 278 {"SEQUENCE (SIZE (1..10))",4,{syntax_error,'END'}}, 279 {"SET { i INTEGER",4,{syntax_error,'END'}}, 280 {"SET { ...",4,{syntax_error,'END'}}, 281 {"SET SIZE (1..10)",4,{syntax_error,'END'}}, 282 {"SET (SIZE (1..10))",4,{syntax_error,'END'}}, 283 {"SET { ... !42 xxx",3,{syntax_error,'xxx'}}, 284 {"SET { ... !42, a INTEGER,",3,{syntax_error,','}}, 285 {"[",4,{syntax_error,'END'}}, 286 {"[42",4,{syntax_error,'END'}} 287 ], 288 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 289 run(L, "Types", Config), 290 ok. 291 292values(Config) -> 293 Head = "Values DEFINITIONS AUTOMATIC TAGS ::=\n" 294 "BEGIN\n" 295 " value Type ::= ", 296 End = "\nEND\n", 297 L0 = [{"",4,{syntax_error,'END'}} 298 ], 299 L = [{Head++S++End,Line,E} || {S,Line,E} <- L0], 300 run(L, "Values", Config), 301 ok. 302 303run(List, File, Config) -> 304 run(List, File, Config, asn1ct_parser2). 305 306run(List, File0, Config, Module) -> 307 Base = File0 ++ ".asn1", 308 File = filename:join(proplists:get_value(priv_dir, Config), Base), 309 case run_1(List, Base, File, Module, 0) of 310 0 -> ok; 311 Errors -> ct:fail(Errors) 312 end. 313 314run_1([{Source,Line,Error}=Exp|T], Base, File, Module, N) -> 315 ok = file:write_file(File, Source), 316 io:format("~s", [Source]), 317 case asn1ct:compile(File) of 318 {error,[{structured_error,{Base,L},Module,E}]} -> 319 case {L,E} of 320 {Line,Error} -> 321 run_1(T, Base, File, Module, N); 322 {Line,OtherError} -> 323 io:format("*** Wrong error: ~p, expected ~p ***\n", 324 [OtherError,Error]), 325 run_1(T, Base, File, Module, N+1); 326 {OtherLine,Error} -> 327 io:format("*** Wrong line: ~p, expected ~p ***\n", 328 [OtherLine,Line]), 329 run_1(T, Base, File, Module, N+1); 330 {_,_} -> 331 io:format("*** Wrong line: ~p, expected ~p ***", 332 [L,Line]), 333 io:format("*** Wrong error: ~p, expected ~p ***\n", 334 [E,Error]), 335 run_1(T, Base, File, Module, N+1) 336 end; 337 Other -> 338 io:format("~p\nGOT: ~p", [Exp,Other]) 339 end; 340run_1([], _, _, _, N) -> 341 N. 342