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(ram_file_SUITE). 22 23-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, 24 init_per_group/2,end_per_group/2, 25 %% init/1, fini/1, 26 init_per_testcase/2, end_per_testcase/2]). 27-export([open_modes/1, open_old_modes/1, pread_pwrite/1, position/1, 28 truncate/1, sync/1, get_set_file/1, compress/1, uuencode/1, 29 large_file_errors/1, large_file_light/1, 30 large_file_heavy/0, large_file_heavy/1]). 31 32-include_lib("common_test/include/ct.hrl"). 33-include_lib("kernel/include/file.hrl"). 34 35-define(FILE_MODULE, file). % Name of module to test 36-define(RAM_FILE_MODULE, ram_file). % Name of module to test 37 38%%-------------------------------------------------------------------------- 39 40suite() -> 41 [{ct_hooks,[ts_install_cth]}, 42 {timetrap,{minutes,1}}]. 43 44all() -> 45 [open_modes, open_old_modes, pread_pwrite, position, 46 truncate, sync, get_set_file, compress, uuencode, 47 large_file_errors, large_file_light, large_file_heavy]. 48 49groups() -> 50 []. 51 52init_per_suite(Config) -> 53 Config. 54 55end_per_suite(_Config) -> 56 ok. 57 58init_per_group(_GroupName, Config) -> 59 Config. 60 61end_per_group(_GroupName, Config) -> 62 Config. 63 64 65init_per_testcase(Func, Config) -> 66 Config. 67 68end_per_testcase(_Func, Config) -> 69 Config. 70 71%%-------------------------------------------------------------------------- 72%% Test suites 73 74%% Test that the basic read, write and binary options works for open/2. 75open_modes(Config) when is_list(Config) -> 76 Str1 = "The quick brown fox ", 77 Str2 = "jumps over a lazy dog ", 78 Str = Str1 ++ Str2, 79 Bin1 = list_to_binary(Str1), 80 Bin2 = list_to_binary(Str2), 81 Bin = list_to_binary(Str), 82 %% 83 open_read_write(?FILE_MODULE, Str1, [ram, read, write], Str2), 84 open_read(?FILE_MODULE, Str, [ram]), 85 open_read_write(?FILE_MODULE, Bin1, [ram, binary, read, write], Bin2), 86 open_read(?FILE_MODULE, Bin, [ram, binary, read]), 87 %% 88 ok. 89 90%% Test that the old style read, write and binary options 91%% works for open/2. 92open_old_modes(Config) when is_list(Config) -> 93 Str1 = "The quick brown fox ", 94 Str2 = "jumps over a lazy dog ", 95 Str = Str1 ++ Str2, 96 Bin1 = list_to_binary(Str1), 97 Bin2 = list_to_binary(Str2), 98 Bin = list_to_binary(Str), 99 %% 100 open_read_write(?RAM_FILE_MODULE, Str1, read_write, Str2), 101 open_read(?RAM_FILE_MODULE, Str, read), 102 open_read_write(?RAM_FILE_MODULE, Bin1, {binary, read_write}, Bin2), 103 open_read(?RAM_FILE_MODULE, Bin, {binary, read}), 104 %% 105 ok. 106 107open_read_write(Module, Data1, Options, Data2) -> 108 io:format("~p:open_read_write(~p, ~p, ~p, ~p)~n", 109 [?MODULE, Module, Data1, Options, Data2]), 110 %% 111 Size1 = sizeof(Data1), 112 Size2 = sizeof(Data2), 113 Data = append(Data1, Data2), 114 Size = Size1 + Size2, 115 %% 116 {ok, Fd} = Module:open(Data1, Options), 117 {ok, Data1} = Module:read(Fd, Size1), 118 eof = Module:read(Fd, 1), 119 {ok, Zero} = Module:read(Fd, 0), 120 0 = sizeof(Zero), 121 ok = Module:write(Fd, Data2), 122 {ok, 0} = Module:position(Fd, bof), 123 {ok, Data} = Module:read(Fd, Size), 124 eof = Module:read(Fd, 1), 125 {ok, Zero} = Module:read(Fd, 0), 126 ok = Module:close(Fd), 127 %% 128 ok. 129 130open_read(Module, Data, Options) -> 131 io:format("~p:open_read(~p, ~p, ~p)~n", 132 [?MODULE, Module, Data, Options]), 133 %% 134 Size = sizeof(Data), 135 %% 136 {ok, Fd} = Module:open(Data, Options), 137 {ok, Data} = Module:read(Fd, Size), 138 eof = Module:read(Fd, 1), 139 {ok, Zero} = Module:read(Fd, 0), 140 0 = sizeof(Zero), 141 {error, ebadf} = Module:write(Fd, Data), 142 {ok, 0} = Module:position(Fd, bof), 143 {ok, Data} = Module:read(Fd, Size), 144 eof = Module:read(Fd, 1), 145 {ok, Zero} = Module:read(Fd, 0), 146 ok = Module:close(Fd), 147 %% 148 ok. 149 150 151 152%% Test that pread/2,3 and pwrite/2,3 works. 153pread_pwrite(Config) when is_list(Config) -> 154 Str = "Flygande bäckaziner söka hwila på mjuqa tuvor x", 155 Bin = list_to_binary(Str), 156 %% 157 pread_pwrite_test(?FILE_MODULE, Str, [ram, read, write]), 158 pread_pwrite_test(?FILE_MODULE, Bin, [ram, binary, read, write]), 159 pread_pwrite_test(?RAM_FILE_MODULE, Str, [read, write]), 160 pread_pwrite_test(?RAM_FILE_MODULE, Bin, {binary, read_write}), 161 %% 162 ok. 163 164pread_pwrite_test(Module, Data, Options) -> 165 io:format("~p:pread_pwrite_test(~p, ~p, ~p)~n", 166 [?MODULE, Module, Data, Options]), 167 %% 168 Size = sizeof(Data), 169 %% 170 {ok, Fd} = Module:open([], Options), 171 ok = Module:pwrite(Fd, 0, Data), 172 {ok, Data} = Module:pread(Fd, 0, Size+1), 173 eof = Module:pread(Fd, Size+1, 1), 174 {ok, Zero} = Module:pread(Fd, Size+1, 0), 175 0 = sizeof(Zero), 176 ok = Module:pwrite(Fd, [{0, Data}, {Size+17, Data}]), 177 {ok, [Data, 178 eof, 179 Data, 180 Zero]} = Module:pread(Fd, [{Size+17, Size+1}, 181 {2*Size+17+1, 1}, 182 {0, Size}, 183 {2*Size+17+1, 0}]), 184 ok = Module:close(Fd), 185 %% 186 ok. 187 188%% Test that position/2 works. 189position(Config) when is_list(Config) -> 190 Str = "Att vara eller icke vara, det är frågan. ", 191 Bin = list_to_binary(Str), 192 %% 193 position_test(?FILE_MODULE, Str, [ram, read]), 194 position_test(?FILE_MODULE, Bin, [ram, binary]), 195 position_test(?RAM_FILE_MODULE, Str, [read]), 196 position_test(?RAM_FILE_MODULE, Bin, {binary, read}), 197 %% 198 ok. 199 200position_test(Module, Data, Options) -> 201 io:format("~p:position_test(~p, ~p, ~p)~n", 202 [?MODULE, Module, Data, Options]), 203 %% 204 Size = sizeof(Data), 205 Size_7 = Size+7, 206 %% 207 Slice_0_2 = slice(Data, 0, 2), 208 Slice_0_3 = slice(Data, 0, 3), 209 Slice_2_5 = slice(Data, 2, 5), 210 Slice_3_4 = slice(Data, 3, 4), 211 Slice_5 = slice(Data, 5, Size), 212 %% 213 {ok, Fd} = Module:open(Data, Options), 214 %% 215 io:format("CUR positions"), 216 {ok, Slice_0_2} = Module:read(Fd, 2), 217 {ok, 2} = Module:position(Fd, cur), 218 {ok, Slice_2_5} = Module:read(Fd, 5), 219 {ok, 3} = Module:position(Fd, {cur, -4}), 220 {ok, Slice_3_4} = Module:read(Fd, 4), 221 {ok, 0} = Module:position(Fd, {cur, -7}), 222 {ok, Slice_0_3} = Module:read(Fd, 3), 223 {ok, 0} = Module:position(Fd, {cur, -3}), 224 {error, einval} = Module:position(Fd, {cur, -1}), 225 {ok, 0} = Module:position(Fd, 0), 226 {ok, 2} = Module:position(Fd, {cur, 2}), 227 {ok, Slice_2_5} = Module:read(Fd, 5), 228 {ok, Size_7} = Module:position(Fd, {cur, Size}), 229 {ok, Zero} = Module:read(Fd, 0), 230 0 = sizeof(Zero), 231 eof = Module:read(Fd, 1), 232 %% 233 io:format("Absolute and BOF positions"), 234 {ok, Size} = Module:position(Fd, Size), 235 eof = Module:read(Fd, 1), 236 {ok, 5} = Module:position(Fd, 5), 237 {ok, Slice_5} = Module:read(Fd, Size), 238 {ok, 2} = Module:position(Fd, {bof, 2}), 239 {ok, Slice_2_5} = Module:read(Fd, 5), 240 {ok, 3} = Module:position(Fd, 3), 241 {ok, Slice_3_4} = Module:read(Fd, 4), 242 {ok, 0} = Module:position(Fd, bof), 243 {ok, Slice_0_2} = Module:read(Fd, 2), 244 {ok, Size_7} = Module:position(Fd, {bof, Size_7}), 245 {ok, Zero} = Module:read(Fd, 0), 246 %% 247 io:format("EOF positions"), 248 {ok, Size} = Module:position(Fd, eof), 249 eof = Module:read(Fd, 1), 250 {ok, 5} = Module:position(Fd, {eof, -Size+5}), 251 {ok, Slice_5} = Module:read(Fd, Size), 252 {ok, 2} = Module:position(Fd, {eof, -Size+2}), 253 {ok, Slice_2_5} = Module:read(Fd, 5), 254 {ok, 3} = Module:position(Fd, {eof, -Size+3}), 255 {ok, Slice_3_4} = Module:read(Fd, 4), 256 {ok, 0} = Module:position(Fd, {eof, -Size}), 257 {ok, Slice_0_2} = Module:read(Fd, 2), 258 {ok, Size_7} = Module:position(Fd, {eof, 7}), 259 {ok, Zero} = Module:read(Fd, 0), 260 eof = Module:read(Fd, 1), 261 %% 262 ok. 263 264 265 266%% Test that truncate/1 works. 267truncate(Config) when is_list(Config) -> 268 Str = "Mån ädlare att lida och fördraga " 269 ++ "ett bittert ödes stygn av pilar, ", 270 Bin = list_to_binary(Str), 271 %% 272 ok = truncate_test(?FILE_MODULE, Str, [ram, read, write]), 273 ok = truncate_test(?FILE_MODULE, Bin, [ram, binary, read, write]), 274 ok = truncate_test(?RAM_FILE_MODULE, Str, read_write), 275 ok = truncate_test(?RAM_FILE_MODULE, Bin, [binary, read, write]), 276 %% 277 {error, eacces} = truncate_test(?FILE_MODULE, Str, [ram]), 278 {error, eacces} = truncate_test(?FILE_MODULE, Bin, [ram, binary, read]), 279 {error, eacces} = truncate_test(?RAM_FILE_MODULE, Str, read), 280 {error, eacces} = truncate_test(?RAM_FILE_MODULE, Bin, {binary, read}), 281 %% 282 ok. 283 284truncate_test(Module, Data, Options) -> 285 io:format("~p:truncate_test(~p, ~p, ~p)~n", 286 [?MODULE, Module, Data, Options]), 287 %% 288 Size = sizeof(Data), 289 Size1 = Size-2, 290 Data1 = slice(Data, 0, Size1), 291 %% 292 {ok, Fd} = Module:open(Data, Options), 293 {ok, Size1} = Module:position(Fd, Size1), 294 case Module:truncate(Fd) of 295 ok -> 296 {ok, 0} = Module:position(Fd, 0), 297 {ok, Data1} = Module:read(Fd, Size), 298 ok = Module:close(Fd), 299 ok; 300 Error -> 301 ok = Module:close(Fd), 302 Error 303 end. 304 305 306 307%% Test that sync/1 at least does not crash. 308sync(Config) when is_list(Config) -> 309 Str = "än att ta till vapen mot ett hav av kval. ", 310 Bin = list_to_binary(Str), 311 %% 312 sync_test(?FILE_MODULE, Str, [ram, read, write]), 313 sync_test(?FILE_MODULE, Bin, [ram, binary, read, write]), 314 sync_test(?RAM_FILE_MODULE, Str, read_write), 315 sync_test(?RAM_FILE_MODULE, Bin, [binary, read, write]), 316 %% 317 sync_test(?FILE_MODULE, Str, [ram]), 318 sync_test(?FILE_MODULE, Bin, [ram, binary, read]), 319 sync_test(?RAM_FILE_MODULE, Str, read), 320 sync_test(?RAM_FILE_MODULE, Bin, {binary, read}), 321 %% 322 ok. 323 324sync_test(Module, Data, Options) -> 325 io:format("~p:sync_test(~p, ~p, ~p)~n", 326 [?MODULE, Module, Data, Options]), 327 %% 328 Size = sizeof(Data), 329 %% 330 {ok, Fd} = Module:open(Data, Options), 331 ok = Module:sync(Fd), 332 {ok, Data} = Module:read(Fd, Size+1), 333 ok. 334 335 336 337%% Tests get_file/1, set_file/2, get_file_close/1 and get_size/1. 338get_set_file(Config) when is_list(Config) -> 339 %% These two strings should not be of equal length. 340 Str = "När högan nord blir snöbetäckt, ", 341 Str2 = "får alla harar byta dräkt. ", 342 Bin = list_to_binary(Str), 343 Bin2 = list_to_binary(Str2), 344 %% 345 ok = get_set_file_test(Str, read_write, Str2), 346 ok = get_set_file_test(Bin, [binary, read, write], Bin2), 347 ok = get_set_file_test(Str, read, Str2), 348 ok = get_set_file_test(Bin, [binary, read], Bin2), 349 %% 350 ok. 351 352get_set_file_test(Data, Options, Data2) -> 353 io:format("~p:get_set_file_test(~p, ~p, ~p)~n", 354 [?MODULE, Data, Options, Data2]), 355 %% 356 Size = sizeof(Data), 357 Size2 = sizeof(Data2), 358 %% 359 {ok, Fd} = ?RAM_FILE_MODULE:open(Data, Options), 360 {ok, Size} = ?RAM_FILE_MODULE:get_size(Fd), 361 {ok, Data} = ?RAM_FILE_MODULE:get_file(Fd), 362 {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd), 363 {error, einval} = ?RAM_FILE_MODULE:get_size(Fd), 364 {ok, Fd2} = ?RAM_FILE_MODULE:open(Data, Options), 365 case ?RAM_FILE_MODULE:set_file(Fd2, Data2) of 366 {ok, Size2} -> 367 {ok, Size2} = ?RAM_FILE_MODULE:get_size(Fd2), 368 {ok, Data2} = ?RAM_FILE_MODULE:get_file(Fd2), 369 {ok, Data2} = ?RAM_FILE_MODULE:get_file_close(Fd2), 370 ok; 371 {error, _} = Error -> 372 {ok, Data} = ?RAM_FILE_MODULE:get_file_close(Fd2), 373 Error 374 end. 375 376 377 378%% Test that compress/1 and uncompress/1 works. 379compress(Config) when is_list(Config) -> 380 Data = proplists:get_value(data_dir, Config), 381 Real = filename:join(Data, "realmen.html"), 382 RealGz = filename:join(Data, "realmen.html.gz"), 383 %% 384 %% Uncompress test 385 %% 386 {ok, FdReal} = ?FILE_MODULE:open(Real, []), 387 {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]), 388 {ok, FdRealGz} = ?FILE_MODULE:open(RealGz, []), 389 %% 390 {ok, SzGz} = ?FILE_MODULE:copy(FdRealGz, Fd), 391 {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd), 392 {ok, 0} = ?FILE_MODULE:position(Fd, bof), 393 true = compare(FdReal, Fd), 394 %% 395 true = (SzGz =< Sz), 396 %% 397 %% Compress and uncompress test 398 %% 399 {ok, 0} = ?FILE_MODULE:position(FdReal, bof), 400 {ok, 0} = ?FILE_MODULE:position(Fd, bof), 401 ok = ?FILE_MODULE:truncate(Fd), 402 {ok, Sz} = ?FILE_MODULE:copy(FdReal, Fd), 403 {ok, SzGz} = ?RAM_FILE_MODULE:compress(Fd), 404 {ok, Sz} = ?RAM_FILE_MODULE:uncompress(Fd), 405 {ok, 0} = ?FILE_MODULE:position(Fd, bof), 406 {ok, 0} = ?FILE_MODULE:position(FdReal, bof), 407 true = compare(FdReal, Fd), 408 %% 409 ok = ?FILE_MODULE:close(FdReal), 410 ok = ?FILE_MODULE:close(Fd), 411 ok = ?FILE_MODULE:close(FdRealGz), 412 413 414 %% Test uncompressing data that will be expanded many times. 415 Huge = iolist_to_binary(mk_42(18)), 416 HugeSize = byte_size(Huge), 417 HugeGz = zlib:gzip(Huge), 418 419 {ok,HugeFd} = ?FILE_MODULE:open([], [ram,read,write,binary]), 420 ok = ?FILE_MODULE:write(HugeFd, HugeGz), 421 {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd), 422 {ok,0} = ?FILE_MODULE:position(HugeFd, bof), 423 {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize), 424 425 %% Uncompressing again should do nothing. 426 {ok,HugeSize} = ?RAM_FILE_MODULE:uncompress(HugeFd), 427 {ok,0} = ?FILE_MODULE:position(HugeFd, bof), 428 {ok,Huge} = ?FILE_MODULE:read(HugeFd, HugeSize), 429 430 ok = ?FILE_MODULE:close(HugeFd), 431 432 ok. 433 434mk_42(0) -> 435 [42]; 436mk_42(N) -> 437 B = mk_42(N-1), 438 [B|B]. 439 440%% Test that uuencode/1 and uudecode/1 works. 441uuencode(Config) when is_list(Config) -> 442 Data = proplists:get_value(data_dir, Config), 443 Real = filename:join(Data, "realmen.html"), 444 RealUu = filename:join(Data, "realmen.html.uu"), 445 %% 446 %% Uudecode test 447 %% 448 {ok, FdReal} = ?FILE_MODULE:open(Real, []), 449 {ok, Fd} = ?FILE_MODULE:open([], [ram, read, write]), 450 {ok, FdRealUu} = ?FILE_MODULE:open(RealUu, []), 451 %% 452 {ok, SzUu} = ?FILE_MODULE:copy(FdRealUu, Fd), 453 {ok, Sz} = ?RAM_FILE_MODULE:uudecode(Fd), 454 true = (Sz =< SzUu), 455 {ok, 0} = ?FILE_MODULE:position(Fd, bof), 456 true = compare(FdReal, Fd), 457 %% 458 %% Uuencode and decode test 459 %% 460 F = fun(Offs) -> 461 Size = Sz - Offs, 462 {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}), 463 {ok, 0} = ?FILE_MODULE:position(Fd, bof), 464 ok = ?FILE_MODULE:truncate(Fd), 465 {ok, Size} = ?FILE_MODULE:copy(FdReal, Fd), 466 {ok, SizeUu} = ?RAM_FILE_MODULE:uuencode(Fd), 467 true = (Size =< SizeUu), 468 {ok, Size} = ?RAM_FILE_MODULE:uudecode(Fd), 469 {ok, Offs} = ?FILE_MODULE:position(FdReal, {bof,Offs}), 470 {ok, 0} = ?FILE_MODULE:position(Fd, bof), 471 true = compare(FdReal, Fd) 472 end, 473 lists:foreach(F, lists:seq(0,Sz-1, 43)), 474 475 ok = ?FILE_MODULE:close(FdReal), 476 ok = ?FILE_MODULE:close(Fd), 477 ok = ?FILE_MODULE:close(FdRealUu), 478 %% 479 ok. 480 481 482%% Test error checking of large file offsets. 483large_file_errors(Config) when is_list(Config) -> 484 TwoGig = 1 bsl 31, 485 {ok,Fd} = ?RAM_FILE_MODULE:open("1234567890", [read,write]), 486 {error, einval} = ?FILE_MODULE:read(Fd, TwoGig), 487 {error, badarg} = ?FILE_MODULE:read(Fd, -1), 488 {error, einval} = ?FILE_MODULE:position(Fd, {bof,TwoGig}), 489 {error, einval} = ?FILE_MODULE:position(Fd, {bof,-TwoGig-1}), 490 {error, einval} = ?FILE_MODULE:position(Fd, {bof,-1}), 491 {error, einval} = ?FILE_MODULE:position(Fd, {cur,TwoGig}), 492 {error, einval} = ?FILE_MODULE:position(Fd, {cur,-TwoGig-1}), 493 {error, einval} = ?FILE_MODULE:position(Fd, {eof,TwoGig}), 494 {error, einval} = ?FILE_MODULE:position(Fd, {eof,-TwoGig-1}), 495 {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 1), 496 {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 1), 497 {error, einval} = ?FILE_MODULE:pread(Fd, -1, 1), 498 {error, einval} = ?FILE_MODULE:pwrite(Fd, TwoGig, "@"), 499 {error, einval} = ?FILE_MODULE:pwrite(Fd, -TwoGig-1, "@"), 500 {error, einval} = ?FILE_MODULE:pwrite(Fd, -1, "@"), 501 {error, einval} = ?FILE_MODULE:pread(Fd, TwoGig, 0), 502 {error, einval} = ?FILE_MODULE:pread(Fd, -TwoGig-1, 0), 503 {error, einval} = ?FILE_MODULE:pread(Fd, -1, 0), 504 ok = ?FILE_MODULE:close(Fd), 505 ok. 506 507 508 509%% Test light operations on a \large\ ram_file. 510large_file_light(Config) when is_list(Config) -> 511 PrivDir = proplists:get_value(priv_dir, Config), 512 %% Marker for next test case that is to heavy to run in a suite. 513 ok = ?FILE_MODULE:write_file( 514 filename:join(PrivDir, "large_file_light"), 515 <<"TAG">>), 516 %% 517 Data = "abcdefghijklmnopqrstuvwzyz", 518 Size = sizeof(Data), 519 Max = (1 bsl 31) - 1, 520 Max__1 = Max - 1, 521 {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read]), 522 {ok, Data} = ?FILE_MODULE:read(Fd, Size+1), 523 {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, Max-Size-1}), 524 eof = ?FILE_MODULE:read(Fd, 1), 525 {ok, Max} = ?FILE_MODULE:position(Fd, {bof, Max}), 526 {ok, Zero} = ?FILE_MODULE:read(Fd, 0), 527 0 = sizeof(Zero), 528 eof = ?FILE_MODULE:read(Fd, 1), 529 eof = ?FILE_MODULE:pread(Fd, Max__1, 1), 530 {ok, Zero} = ?FILE_MODULE:pread(Fd, Max, 0), 531 eof = ?FILE_MODULE:pread(Fd, Max, 1), 532 ok. 533 534 535 536large_file_heavy() -> 537 [{timetrap,{minutes,5}}]. 538 539%% Test operations on a maximum size (2 GByte - 1) ram_file. 540large_file_heavy(Config) when is_list(Config) -> 541 PrivDir = proplists:get_value(priv_dir, Config), 542 %% Check previous test case marker. 543 case ?FILE_MODULE:read_file_info( 544 filename:join(PrivDir, "large_file_light")) of 545 {ok,_} -> 546 {skipped,"Too heavy for casual testing!"}; 547 _ -> 548 do_large_file_heavy(Config) 549 end. 550 551do_large_file_heavy(_Config) -> 552 Data = "qwertyuiopasdfghjklzxcvbnm", 553 Size = sizeof(Data), 554 Max = (1 bsl 31) - 1, 555 Max__1 = Max - 1, 556 Max__3 = Max - 3, 557 {ok, Fd} = ?RAM_FILE_MODULE:open(Data, [read,write]), 558 {ok, Data} = ?FILE_MODULE:read(Fd, Size+1), 559 {ok, Max} = ?FILE_MODULE:position(Fd, {eof, Max-Size}), 560 eof = ?FILE_MODULE:read(Fd, 1), 561 erlang:display({allocating,2,'GByte',please,be,patient,'...'}), 562 ok = ?FILE_MODULE:write(Fd, ""), 563 erlang:display({allocating,2,'GByte',succeeded}), 564 {ok, Max__1} = ?FILE_MODULE:position(Fd, {eof, -1}), 565 {ok, [0]} = ?FILE_MODULE:read(Fd, 1), 566 {ok, []} = ?FILE_MODULE:read(Fd, 0), 567 eof = ?FILE_MODULE:read(Fd, 1), 568 ok = ?FILE_MODULE:pwrite(Fd, Max-3, "TAG"), 569 {ok, Max} = ?FILE_MODULE:position(Fd, cur), 570 {ok, Max__3} = ?FILE_MODULE:position(Fd, {eof, -3}), 571 {ok, "TAG"} = ?FILE_MODULE:read(Fd, 3+1), 572 {ok, Max__3} = ?FILE_MODULE:position(Fd, {cur, -3}), 573 ok = ?FILE_MODULE:write(Fd, "tag"), 574 {ok, Max} = ?FILE_MODULE:position(Fd, cur), 575 {ok, 0} = ?FILE_MODULE:position(Fd, bof), 576 {ok, "tag"} = ?FILE_MODULE:pread(Fd, Max__3, 3+1), 577 {ok, 0} = ?FILE_MODULE:position(Fd, cur), 578 ok = ?FILE_MODULE:close(Fd), 579 ok. 580 581%%-------------------------------------------------------------------------- 582%% Utility functions 583 584compare(FdA, FdB) -> 585 Size = 65536, 586 case {?FILE_MODULE:read(FdA, Size), ?FILE_MODULE:read(FdB, Size)} of 587 {{error, _} = Error, _} -> 588 Error; 589 {_, {error, _} = Error} -> 590 Error; 591 {{ok, A}, {ok, B}} -> 592 case compare_data(A, B) of 593 true -> 594 compare(FdA, FdB); 595 false -> 596 false 597 end; 598 {eof, eof} -> 599 true; 600 _ -> 601 false 602 end. 603 604compare_data(A, B) when is_list(A), is_list(B) -> 605 list_to_binary(A) == list_to_binary(B); 606compare_data(A, B) when is_list(A), is_binary(B) -> 607 list_to_binary(A) == B; 608compare_data(A, B) when is_binary(A), is_list(B) -> 609 A == list_to_binary(B); 610compare_data(A, B) when is_binary(A), is_binary(B) -> 611 A == B. 612 613sizeof(Data) when is_list(Data) -> 614 length(Data); 615sizeof(Data) when is_binary(Data) -> 616 byte_size(Data). 617 618append(Data1, Data2) when is_list(Data1), is_list(Data2) -> 619 Data1 ++ Data2; 620append(Data1, Data2) when is_binary(Data1), is_binary(Data2) -> 621 list_to_binary([Data1 | Data2]). 622 623slice(Data, Start, Length) when is_list(Data) -> 624 lists:sublist(Data, Start+1, Length); 625slice(Data, Start, Length) when is_binary(Data) -> 626 {_, Bin} = split_binary(Data, Start), 627 if 628 Length >= byte_size(Bin) -> 629 Bin; 630 true -> 631 {B, _} = split_binary(Bin, Length), 632 B 633 end. 634 635