1%% 2%% %CopyrightBegin% 3%% 4%% Copyright Ericsson AB 2019. 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(bs_size_expr_SUITE). 22-compile(nowarn_shadow_vars). 23 24-export([all/0,suite/0,groups/0,init_per_suite/1, end_per_suite/1, 25 init_per_group/2,end_per_group/2, 26 init_per_testcase/2,end_per_testcase/2, 27 basic/1,size_shadow/1,complex/1, 28 recv/1,no_match/1]). 29 30suite() -> 31 [{ct_hooks,[ts_install_cth]}, 32 {timetrap,{minutes,1}}]. 33 34all() -> 35 [{group,p}]. 36 37groups() -> 38 [{p,test_lib:parallel(), 39 [basic, 40 size_shadow, 41 complex, 42 recv, 43 no_match]}]. 44 45init_per_suite(Config) -> 46 test_lib:recompile(?MODULE), 47 Config. 48 49end_per_suite(_Config) -> 50 ok. 51 52init_per_group(_GroupName, Config) -> 53 Config. 54 55end_per_group(_GroupName, Config) -> 56 Config. 57 58init_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> 59 Config. 60 61end_per_testcase(Case, Config) when is_atom(Case), is_list(Config) -> 62 ok. 63 64basic(_Config) -> 65 <<>> = do_basic(<<1:32>>), 66 <<"abcd">> = do_basic(<<2:32,"abcd">>), 67 no_match = do_basic(<<0:32>>), 68 no_match = do_basic(<<777:32>>), 69 ok. 70 71do_basic(Bin) -> 72 Res = do_basic_1(Bin), 73 74 Res = do_basic_2({tag,Bin}), 75 Res = do_basic_2([list,Bin]), 76 6 = do_basic_2({2,4}), 77 78 Res = do_basic_3(Bin), 79 Res = do_basic_4(Bin), 80 81 {result,Res} = do_basic_5(Bin), 82 case Res of 83 no_match -> 84 ok; 85 _ -> 86 {result,{Res,7777777}} = do_basic_5(<<Bin/binary,7777777:32>>) 87 end, 88 89 Res. 90 91do_basic_1(<<Sz:32,Tail:(4*Sz-4)/binary>>) -> 92 Tail; 93do_basic_1(<<_/binary>>) -> 94 no_match. 95 96do_basic_2({tag,<<Sz:32,Tail:(4*Sz-4)/binary>>}) -> 97 Tail; 98do_basic_2([list,<<Sz:32,Tail:((Sz-1)*4)/binary>>]) -> 99 Tail; 100do_basic_2({A,B}) when is_integer(A), is_integer(B) -> 101 A + B; 102do_basic_2(_) -> 103 no_match. 104 105do_basic_3(Bin) -> 106 WordSize = id(4), 107 case Bin of 108 <<Sz:32,Tail:(WordSize*Sz-WordSize)/binary>> -> 109 Tail; 110 _ -> 111 no_match 112 end. 113 114do_basic_4(Bin) -> 115 WordSize = id(4), 116 F = fun() -> 117 case Bin of 118 <<Sz:32,Tail:(WordSize*Sz-WordSize)/binary>> -> 119 Tail; 120 _ -> 121 no_match 122 end 123 end, 124 F(). 125 126do_basic_5(Bin) -> 127 WordSize = id(4), 128 F = fun() -> 129 Res = case Bin of 130 <<Sz:32,Tail:(WordSize*Sz-WordSize)/binary,More:(8*WordSize)>> -> 131 {Tail,More}; 132 <<Sz:32,Tail:(WordSize*Sz-WordSize)/binary>> -> 133 Tail; 134 _ -> 135 no_match 136 end, 137 {result,Res} 138 end, 139 F(). 140 141size_shadow(_Config) -> 142 12345678 = size_shadow_1(), 143 ok. 144 145size_shadow_1() -> 146 L = 8, 147 Offset = 16, 148 Fs = [fun(<<L:L,B:(L+16)>>) -> B end, 149 fun(<<L:L,B:(L+Offset)>>) -> B end, 150 fun(A) -> 151 Res = (fun([<<L:L,B:(L+16)>>]) -> B end)([A]), 152 Res = (fun([<<L:L,B:(L+Offset)>>]) -> B end)([A]) 153 end, 154 fun(A) -> 155 Res = (fun({<<L:L,B:(L+16)>>,<<L:L,B:(L+16)>>}) -> B end)({A,A}), 156 Res = (fun({<<L:L,B:(L+Offset)>>,<<L:L,B:(L+16)>>}) -> B end)({A,A}), 157 Res = (fun({<<L:L,B:(L+16)>>,<<L:L,B:(L+Offset)>>}) -> B end)({A,A}), 158 Res = (fun({<<L:L,B:(L+Offset)>>,<<L:L,B:(L+Offset)>>}) -> B end)({A,A}) 159 end, 160 fun(A) -> 161 <<Size:L,_/bits>> = A, 162 Inner = fun([L], {#{key1 := <<L:L,B:(L+Offset)>>, 163 key2 := <<L:L,B:(L+Offset)>>}, L}) -> B end, 164 Inner([Size], {#{key1 => A,key2 => A},Size}) 165 end], 166 size_shadow_apply(Fs, <<16:8, 12345678:32>>). 167 168size_shadow_apply([F|Fs], Arg) when is_function(F, 1) -> 169 size_shadow_apply(Fs, Arg, F(Arg)). 170 171size_shadow_apply([F|Fs], Arg, Res) when is_function(F, 1) -> 172 Res = F(Arg), 173 size_shadow_apply(Fs, Arg, Res); 174size_shadow_apply([], _, Res) -> 175 Res. 176 177-record(r, {a,b,c}). 178complex(Config) -> 179 (fun() -> 180 Len = length(id(Config)), 181 Bin = << <<I:13>> || I <- lists:seq(1, Len) >>, 182 <<Bin:(length(Config))/binary-unit:13>> = Bin 183 end)(), 184 185 (fun() -> 186 V = id([a,b,c]), 187 F = fun(<<V:(bit_size(<<0:(length(V))>>)*8)/signed-integer>>) -> 188 V; 189 ({A,B}) -> 190 A + B 191 end, 192 -1 = F(<<-1:(length(V)*8)>>), 193 7 = F({3,4}) 194 end)(), 195 196 (fun() -> 197 A = a, 198 B = b, 199 F = fun(<<A:16,B:16,C:(A+B),D/bits>>) -> 200 {A,B,C,D}; 201 (<<A:16,B:16>>) -> 202 {A,B}; 203 (<<A:8,B:8>>) -> 204 {A,B} 205 end, 206 {13,21,16#cafebeef,<<"more">>} = F(<<13:16,21:16,16#cafebeef:34,"more">>), 207 {100,500} = F(<<100:16,500:16>>), 208 {157,77} = F(<<157:8,77:8>>), 209 {A,B} 210 end)(), 211 212 (fun() -> 213 Two = id(2), 214 F = fun(a, <<_:(#r.a - Two)/binary,Int:8,_/binary>>) -> Int; 215 (b, <<_:(#r.b - Two)/binary,Int:8,_/binary>>) -> Int; 216 (c, <<_:(#r.c - Two)/binary,Int:8,_/binary>>) -> Int 217 end, 218 1 = F(a, <<1,2,3>>), 219 2 = F(b, <<1,2,3>>), 220 3 = F(c, <<1,2,3>>) 221 end)(), 222 223 (fun() -> 224 Bin = <<1,2,3,4>>, 225 F = fun(R) -> 226 <<First:(R#r.a)/binary,Tail/binary>> = Bin, 227 {First,Tail} 228 end, 229 {<<>>,<<1,2,3,4>>} = F(#r{a=0}), 230 {<<1>>,<<2,3,4>>} = F(#r{a=1}), 231 {<<1,2>>,<<3,4>>} = F(#r{a=2}), 232 {<<1,2,3>>,<<4>>} = F(#r{a=3}), 233 {<<1,2,3,4>>,<<>>} = F(#r{a=4}) 234 end)(), 235 236 [] = fun() -> 237 case day of 238 V0 -> ok 239 end, 240 %% A bug in v3_core prevented V0 as being seen as used, 241 %% and because of that, V0 would not be exported from the 242 %% case above. 243 [0 || <<42:(V0#{key => value})>> <- []] 244 end(), 245 246 ok. 247 248recv(_Config) -> 249 R = fun(Msg) -> 250 self() ! Msg, 251 Res = receive 252 <<L,I:(L-1)/unit:8,X:32>> -> {I,X}; 253 <<L,I:(L-1)/unit:8,X:64>> -> {I,X} 254 end, 255 self() ! {tag,[Msg]}, 256 Res = receive 257 {tag,[<<L,I:(8*(L-1)),X:32>>]} -> {I,X}; 258 {tag,[<<L,I:(8*(L-1)),X:64>>]} -> {I,X} 259 end 260 end, 261 {1234,16#deadbeef} = R(<<3,1234:16,16#deadbeef:32>>), 262 {99,16#cafebeeff00d} = R(<<2,99:8,16#cafebeeff00d:64>>), 263 ok. 264 265no_match(_Config) -> 266 B = id(<<1,2,3,4>>), 267 no_match = case B of 268 <<Int:(bit_size(B)-1)>> -> Int; 269 <<Int:(bit_size(B)*2)>> -> Int; 270 <<Int:(length(B))>> -> Int; 271 _ -> no_match 272 end, 273 no_match = case B of 274 <<L:8,Int2:(is_integer(L))>> -> Int2; 275 <<L:8,Int2:(L+3.0)>> -> Int2; 276 _ -> no_match 277 end, 278 279 no_match = case B of 280 <<Int3:(1/0)>> -> Int3; 281 _ -> no_match 282 end, 283 284 no_match = case B of 285 <<Int4:all>> -> Int4; 286 <<Int4:bad_size>> -> Int4; 287 _ -> no_match 288 end, 289 290 [] = [X || <<X:(is_list(B))/binary>> <= B], 291 <<>> = << <<X:32>> || <<X:(is_list(B))/binary>> <= B >>, 292 293 ok. 294 295id(I) -> 296 I. 297