1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2001-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(testConstraints).
22
23-export([int_constraints/1,refed_NNL_name/1]).
24
25
26-include_lib("common_test/include/ct.hrl").
27
28int_constraints(Rules) ->
29
30    %%==========================================================
31    %% SingleValue ::=  INTEGER (1)
32    %%==========================================================
33
34    range_error(Rules, 'SingleValue', 0),
35    roundtrip('SingleValue', 1),
36    range_error(Rules, 'SingleValue', 2),
37    range_error(Rules, 'SingleValue', 1000),
38
39    %%==========================================================
40    %% SingleValue2 ::=  INTEGER (1..20)
41    %%==========================================================
42
43    range_error(Rules, 'SingleValue2', 0),
44    roundtrip('SingleValue2', 1),
45    roundtrip('SingleValue2', 20),
46    range_error(Rules, 'SingleValue2', 21),
47    range_error(Rules, 'SingleValue2', 1000),
48
49    %%==========================================================
50    %% SingleValue3 ::=  INTEGER (Predefined | 5 | 10)
51    %% Testcase for OTP-10139. A single value subtyping of an integer type
52    %% where one value is predefined.
53    %%==========================================================
54
55    roundtrip('SingleValue3', 1),
56    roundtrip('SingleValue3', 5),
57    roundtrip('SingleValue3', 10),
58
59    %%==========================================================
60    %% Range2to19 ::=  INTEGER (1<..<20)
61    %%==========================================================
62
63    range_error(Rules, 'Range2to19', 1),
64    roundtrip('Range2to19', 2),
65    roundtrip('Range2to19', 19),
66    range_error(Rules, 'Range2to19', 20),
67
68    %%==========================================================
69    %% Tests for Range above 16^4 up to maximum supported by asn1 assuming the
70    %% octet length field is encoded on max 8 bits
71    %%==========================================================
72    LastNumWithoutLengthEncoding = 65536,
73    roundtrip('Range256to65536', LastNumWithoutLengthEncoding),
74    roundtrip('Range256to65536Ext', LastNumWithoutLengthEncoding),
75    roundtrip('Range256to65536Ext', 42),
76
77    FirstNumWithLengthEncoding = 65537,
78    roundtrip('LargeConstraints', 'RangeMax', FirstNumWithLengthEncoding),
79
80    FirstNumOver16_6 = 16777217,
81    roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_6),
82
83    FirstNumOver16_8 = 4294967297,
84    roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_8),
85
86    FirstNumOver16_10 = 1099511627776,
87    roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_10),
88
89    FirstNumOver16_10 = 1099511627776,
90    roundtrip('LargeConstraints', 'RangeMax', FirstNumOver16_10),
91
92    HalfMax = 1 bsl (128*8),
93    roundtrip('LargeConstraints', 'RangeMax', HalfMax),
94
95    Max = 1 bsl (255*8),
96    roundtrip('LargeConstraints', 'RangeMax', Max),
97
98    %% Random number within longlong range
99    LongLong = 12672809400538808320,
100    roundtrip('LongLong', LongLong),
101    roundtrip('LongLongExt', LongLong),
102    roundtrip('LongLongExt', -10000),
103
104    %%==========================================================
105    %%  Constraint Combinations (Duboisson p. 285)
106    %%  I ::= INTEGER (0|15..269)
107    %%==========================================================
108
109    range_error(Rules, 'I', -1),
110    roundtrip('I', 0),
111    roundtrip('I', 15),
112    roundtrip('I', 20),
113    roundtrip('I', 269),
114    range_error(Rules, 'I', 270),
115
116    %%==========================================================
117    %%  Constraint Combinations (Duboisson p. 285)
118    %%  X1 ::= INTEGER (1..4|8|10|20)
119    %%==========================================================
120
121    range_error(Rules, 'X1', 0),
122    roundtrip('X1', 1),
123    roundtrip('X1', 4),
124    roundtrip('X1', 8),
125    roundtrip('X1', 10),
126    roundtrip('X1', 20),
127    range_error(Rules, 'X1', 21),
128
129    %%==========================================================
130    %%  Union of single values
131    %%  Sv1 ::= INTEGER (2|3|17)
132    %%  Sv2 ::= INTEGER (2|3|17, ...)
133    %%  Sv3 ::= INTEGER {a(2),b(3),z(17)} (2|3|17, ...)
134    %%==========================================================
135
136    range_error(Rules, 'Sv1', 1),
137    range_error(Rules, 'Sv1', 18),
138    roundtrip('Sv1', 2),
139    roundtrip('Sv1', 3),
140    roundtrip('Sv1', 7),
141
142    %% Encoded as root
143    v_roundtrip(Rules, 'Sv2', 2),
144    v_roundtrip(Rules, 'Sv2', 3),
145    v_roundtrip(Rules, 'Sv2', 17),
146
147    %% Encoded as extension
148    v_roundtrip(Rules, 'Sv2', 1),
149    v_roundtrip(Rules, 'Sv2', 4),
150    v_roundtrip(Rules, 'Sv2', 18),
151
152    %% Encoded as root
153    v_roundtrip(Rules, 'Sv3', a),
154    v_roundtrip(Rules, 'Sv3', b),
155    v_roundtrip(Rules, 'Sv3', z),
156    v_roundtrip(Rules, 'Sv3', 2, a),
157    v_roundtrip(Rules, 'Sv3', 3, b),
158    v_roundtrip(Rules, 'Sv3', 17, z),
159
160    %% Encoded as extension
161    v_roundtrip(Rules, 'Sv3', 1),
162    v_roundtrip(Rules, 'Sv3', 4),
163    v_roundtrip(Rules, 'Sv3', 18),
164
165    %%==========================================================
166    %%  SemiConstrained
167    %%==========================================================
168
169    roundtrip('SemiConstrained', 100),
170    v_roundtrip(Rules, 'SemiConstrained', 100+128),
171    roundtrip('SemiConstrained', 397249742397243),
172    roundtrip('SemiConstrained', 100 + 1 bsl 128*8),
173    roundtrip('SemiConstrained', 100 + 1 bsl 256*8),
174
175    roundtrip('NegSemiConstrained', -128),
176    v_roundtrip(Rules, 'NegSemiConstrained', 0),
177    roundtrip('NegSemiConstrained', -1),
178    roundtrip('NegSemiConstrained', 500),
179
180    roundtrip('SemiConstrainedExt', -65536),
181    roundtrip('SemiConstrainedExt', 0),
182    roundtrip('SemiConstrainedExt', 42),
183    v_roundtrip(Rules, 'SemiConstrainedExt', 42+128),
184    roundtrip('SemiConstrainedExt', 100),
185    roundtrip('SemiConstrainedExt', 47777789),
186    roundtrip('SemiConstrainedExt', 42 + 1 bsl 128*8),
187    roundtrip('SemiConstrainedExt', 42 + 1 bsl 256*8),
188
189    roundtrip('NegSemiConstrainedExt', -1023),
190    roundtrip('NegSemiConstrainedExt', -128),
191    roundtrip('NegSemiConstrainedExt', -1),
192    v_roundtrip(Rules, 'NegSemiConstrainedExt', 0),
193    roundtrip('NegSemiConstrainedExt', 500),
194
195    %%==========================================================
196    %%  SIZE Constraint (Duboisson p. 268)
197    %%  T ::=  IA5String (SIZE (1|2, ..., SIZE (1|2|3)))
198    %%  T2 ::= IA5String (SIZE (1|2, ..., 3))
199    %%==========================================================
200
201    roundtrip('T', "IA"),
202    roundtrip('T', "IAB"),
203    roundtrip('T', "IABC"),
204    roundtrip('T2', "IA"),
205    roundtrip('T2', "IAB"),
206    roundtrip('T2', "IABC"),
207
208    %%==========================================================
209    %%  More SIZE Constraints
210    %%==========================================================
211
212    roundtrip('FixedSize', <<"0123456789">>),
213    roundtrip('FixedSize2', <<"0123456789">>),
214    roundtrip('FixedSize2', <<"0123456789abcdefghij">>),
215
216    range_error(Rules, 'FixedSize', "short"),
217    range_error(Rules, 'FixedSize2', "short"),
218
219    [roundtrip('VariableSize', list_to_binary(lists:seq($A, $A+L-1))) ||
220	L <- lists:seq(1, 10)],
221
222    roundtrip_enc('ShorterExt', "a", shorter_ext(Rules, "a")),
223    roundtrip('ShorterExt', "abcde"),
224    roundtrip('ShorterExt', "abcdef"),
225
226    %%==========================================================
227    %%  Unions of INTEGER constraints
228    %%==========================================================
229    seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 7580),
230    seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 9600),
231    seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 18050),
232    seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 19000),
233    seq_roundtrip(Rules, 'SeqOverlapping', 'SeqNonOverlapping', 26900),
234
235    %%==========================================================
236    %%  Constraints from object fields.
237    %%==========================================================
238    range_error(Rules, 'IntObjectConstr', 1),
239    roundtrip('IntObjectConstr', 2),
240    roundtrip('IntObjectConstr', 3),
241    roundtrip('IntObjectConstr', 4),
242    range_error(Rules, 'IntObjectConstr', 5),
243
244
245    %%==========================================================
246    %% INTEGER constraints defined using named INTEGERs.
247    %%==========================================================
248    42 = 'Constraints':'constrainedNamedInt-1'(),
249    100 = 'Constraints':'constrainedNamedInt-2'(),
250    range_error(Rules, 'ConstrainedNamedInt', 41),
251    roundtrip('ConstrainedNamedInt', v1),
252    range_error(Rules, 'ConstrainedNamedInt', 43),
253
254    range_error(Rules, 'SeqWithNamedInt', {'SeqWithNamedInt',-100}),
255    roundtrip('SeqWithNamedInt', {'SeqWithNamedInt',v2}),
256
257    ok.
258
259%% PER: Ensure that if the lower bound is Lb, Lb+16#80 is encoded
260%% in two bytes as 16#0180. (Not in three bytes as 16#010080.)
261v(ber, 'SemiConstrained', 100+128) -> "020200E4";
262v(per, 'SemiConstrained', 100+128) -> "0180";
263v(uper, 'SemiConstrained', 100+128) -> "0180";
264v(ber, 'NegSemiConstrained', 0) -> "020100";
265v(per, 'NegSemiConstrained', 0) -> "0180";
266v(uper, 'NegSemiConstrained', 0) -> "0180";
267v(ber, 'SemiConstrainedExt', 42+128) -> "020200AA";
268v(per, 'SemiConstrainedExt', 42+128) -> "000180";
269v(uper, 'SemiConstrainedExt', 42+128) -> "00C000";
270v(ber, 'NegSemiConstrainedExt', 0) -> "020100";
271v(per, 'NegSemiConstrainedExt', 0) -> "000180";
272v(uper, 'NegSemiConstrainedExt', 0) -> "00C000";
273v(ber, 'Sv2', 1) -> "020101";
274v(per, 'Sv2', 1) -> "800101";
275v(uper, 'Sv2', 1) -> "808080";
276v(ber, 'Sv2', 2) -> "020102";
277v(per, 'Sv2', 2) -> "00";
278v(uper, 'Sv2', 2) -> "00";
279v(ber, 'Sv2', 3) -> "020103";
280v(per, 'Sv2', 3) -> "08";
281v(uper, 'Sv2', 3) -> "08";
282v(ber, 'Sv2', 4) -> "020104";
283v(per, 'Sv2', 4) -> "800104";
284v(uper, 'Sv2', 4) -> "808200";
285v(ber, 'Sv2', 17) -> "020111";
286v(per, 'Sv2', 17) -> "78";
287v(uper, 'Sv2', 17) -> "78";
288v(ber, 'Sv2', 18) -> "020112";
289v(per, 'Sv2', 18) -> "800112";
290v(uper, 'Sv2', 18) -> "808900";
291v(Rule, 'Sv3', a) -> v(Rule, 'Sv2', 2);
292v(Rule, 'Sv3', b) -> v(Rule, 'Sv2', 3);
293v(Rule, 'Sv3', z) -> v(Rule, 'Sv2', 17);
294v(Rule, 'Sv3', Val) when is_integer(Val) -> v(Rule, 'Sv2', Val).
295
296shorter_ext(per, "a") -> <<16#80,16#01,16#61>>;
297shorter_ext(uper, "a") -> <<16#80,16#E1>>;
298shorter_ext(ber, _) -> none;
299shorter_ext(jer, _) -> none.
300
301refed_NNL_name(_Erule) ->
302    roundtrip('AnotherThing', fred),
303    {error,_Reason} = 'Constraints':encode('AnotherThing', fred3).
304
305v_roundtrip(jer,_,_) -> ok;
306v_roundtrip(Erule, Type, Value) ->
307    Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type, Value)),
308    Encoded = roundtrip('Constraints', Type, Value).
309
310v_roundtrip(jer,_,_,_) -> ok;
311v_roundtrip(Erule, Type, Value, Expected) ->
312    Encoded = asn1_test_lib:hex_to_bin(v(Erule, Type, Value)),
313    Encoded = asn1_test_lib:roundtrip_enc('Constraints', Type, Value, Expected).
314
315roundtrip(Type, Value) ->
316    roundtrip('Constraints', Type, Value).
317
318roundtrip(Module, Type, Value) ->
319    asn1_test_lib:roundtrip_enc(Module, Type, Value).
320
321roundtrip_enc(Type, Value, Enc) ->
322    Encoded = asn1_test_lib:roundtrip_enc('Constraints', Type, Value),
323    case Enc of
324	none -> ok;
325	Encoded -> ok
326    end.
327
328range_error(ber, Type, Value) ->
329    %% BER: Values outside the effective range should be rejected
330    %% on decode.
331    {ok,Encoded} = 'Constraints':encode(Type, Value),
332    {error,{asn1,_}} = 'Constraints':decode(Type, Encoded),
333    ok;
334range_error(Per, Type, Value) when Per =:= per; Per =:= uper; Per =:= jer ->
335    %% (U)PER: Values outside the effective range should be rejected
336    %% on encode.
337    {error,_} = 'Constraints':encode(Type, Value),
338    ok.
339
340seq_roundtrip(Rules, Seq1, Seq2, Val) ->
341    Enc = roundtrip(Seq1, {Seq1,Val}),
342    case Rules of
343	ber ->
344	    roundtrip(Seq2, {Seq2,Val});
345	_ ->
346	    roundtrip_enc(Seq2, {Seq2,Val}, Enc)
347    end.
348