|
27 | 27 | -include_lib("stdlib/include/erl_compile.hrl"). |
28 | 28 | -include_lib("stdlib/include/assert.hrl"). |
29 | 29 |
|
30 | | --export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, |
| 30 | +-export([all/0, suite/0,groups/0,init_per_suite/1, end_per_suite/1, |
31 | 31 | init_per_group/2,end_per_group/2, |
32 | 32 | app_test/1,appup_test/1,bigE_roundtrip/1, |
33 | 33 | debug_info/4, custom_debug_info/1, custom_compile_info/1, |
34 | | - file_1/1, forms_2/1, module_mismatch/1, outdir/1, |
| 34 | + file_1/1, forms_2/1, string_1/1, module_mismatch/1, outdir/1, |
35 | 35 | binary/1, makedep/1, cond_and_ifdef/1, listings/1, listings_big/1, |
36 | 36 | other_output/1, encrypted_abstr/1, |
37 | 37 | strict_record/1, utf8_atoms/1, utf8_functions/1, extra_chunks/1, |
@@ -60,7 +60,7 @@ suite() -> [{ct_hooks,[ts_install_cth]}]. |
60 | 60 |
|
61 | 61 | all() -> |
62 | 62 | [app_test, appup_test, bigE_roundtrip, file_1, |
63 | | - forms_2, module_mismatch, outdir, |
| 63 | + forms_2, string_1, module_mismatch, outdir, |
64 | 64 | binary, makedep, cond_and_ifdef, listings, listings_big, |
65 | 65 | other_output, encrypted_abstr, tuple_calls, |
66 | 66 | strict_record, utf8_atoms, utf8_functions, extra_chunks, |
@@ -326,6 +326,169 @@ forms_compile_and_load(Code, Opts) -> |
326 | 326 | false = code:purge(simple), |
327 | 327 | ok. |
328 | 328 |
|
| 329 | +string_1(_Config) -> |
| 330 | + %% Basic compilation from string. |
| 331 | + {ok,foo,BinFoo} = compile:string("-module(foo). -export([bar/0]). bar() -> hello."), |
| 332 | + {module,foo} = code:load_binary(foo, "foo.erl", BinFoo), |
| 333 | + hello = foo:bar(), |
| 334 | + true = code:delete(foo), |
| 335 | + false = code:purge(foo), |
| 336 | + |
| 337 | + %% Binary input. |
| 338 | + {ok,binmod,BinMod} = compile:string(<<"-module(binmod). -export([g/0]). g() -> ok.">>), |
| 339 | + {module,binmod} = code:load_binary(binmod, "binmod.erl", BinMod), |
| 340 | + ok = binmod:g(), |
| 341 | + true = code:delete(binmod), |
| 342 | + false = code:purge(binmod), |
| 343 | + |
| 344 | + %% Preprocessor: macros with -define. |
| 345 | + {ok,macmod,BinMac} = compile:string( |
| 346 | + "-module(macmod). -export([f/0]).\n" |
| 347 | + "-define(X, 42).\n" |
| 348 | + "f() -> ?X.\n"), |
| 349 | + {module,macmod} = code:load_binary(macmod, "macmod.erl", BinMac), |
| 350 | + 42 = macmod:f(), |
| 351 | + true = code:delete(macmod), |
| 352 | + false = code:purge(macmod), |
| 353 | + |
| 354 | + %% Preprocessor: records. |
| 355 | + {ok,recmod,BinRec} = compile:string( |
| 356 | + "-module(recmod). -export([new/0]).\n" |
| 357 | + "-record(point, {x = 0, y = 0}).\n" |
| 358 | + "new() -> #point{x = 1, y = 2}.\n"), |
| 359 | + {module,recmod} = code:load_binary(recmod, "recmod.erl", BinRec), |
| 360 | + {point,1,2} = recmod:new(), |
| 361 | + true = code:delete(recmod), |
| 362 | + false = code:purge(recmod), |
| 363 | + |
| 364 | + %% Preprocessor: -ifdef/-endif. |
| 365 | + {ok,ifmod,BinIf} = compile:string( |
| 366 | + "-module(ifmod). -export([f/0]).\n" |
| 367 | + "-ifdef(NOTDEFINED).\n" |
| 368 | + "f() -> wrong.\n" |
| 369 | + "-else.\n" |
| 370 | + "f() -> right.\n" |
| 371 | + "-endif.\n"), |
| 372 | + {module,ifmod} = code:load_binary(ifmod, "ifmod.erl", BinIf), |
| 373 | + right = ifmod:f(), |
| 374 | + true = code:delete(ifmod), |
| 375 | + false = code:purge(ifmod), |
| 376 | + |
| 377 | + %% Preprocessor: predefined macros via options. |
| 378 | + {ok,defmod,BinDef} = compile:string( |
| 379 | + "-module(defmod). -export([f/0]).\n" |
| 380 | + "f() -> ?MY_VALUE.\n", |
| 381 | + [{d,'MY_VALUE',99}]), |
| 382 | + {module,defmod} = code:load_binary(defmod, "defmod.erl", BinDef), |
| 383 | + 99 = defmod:f(), |
| 384 | + true = code:delete(defmod), |
| 385 | + false = code:purge(defmod), |
| 386 | + |
| 387 | + %% Preprocessor: ?MODULE. |
| 388 | + {ok,modmac,BinModMac} = compile:string( |
| 389 | + "-module(modmac). -export([name/0]).\n" |
| 390 | + "name() -> ?MODULE.\n"), |
| 391 | + {module,modmac} = code:load_binary(modmac, "modmac.erl", BinModMac), |
| 392 | + modmac = modmac:name(), |
| 393 | + true = code:delete(modmac), |
| 394 | + false = code:purge(modmac), |
| 395 | + |
| 396 | + %% Source option. |
| 397 | + {ok,srcmod,BinSrc} = compile:string( |
| 398 | + "-module(srcmod). -export([f/0]). f() -> ok.", |
| 399 | + [{source,"my_source.erl"}]), |
| 400 | + {module,srcmod} = code:load_binary(srcmod, "srcmod.erl", BinSrc), |
| 401 | + Info = srcmod:module_info(compile), |
| 402 | + SrcInfo = proplists:get_value(source, Info), |
| 403 | + true = lists:suffix("my_source.erl", SrcInfo), |
| 404 | + true = code:delete(srcmod), |
| 405 | + false = code:purge(srcmod), |
| 406 | + |
| 407 | + %% Syntax error returns error. |
| 408 | + error = compile:string("-module(bad). f( ->"), |
| 409 | + |
| 410 | + %% Syntax error with return_errors option. |
| 411 | + {error,[{"string",[{_,_,_}|_]}],_} = |
| 412 | + compile:string("-module(bad). f( ->", [return_errors]), |
| 413 | + |
| 414 | + %% Source option affects error filenames. |
| 415 | + {error,[{"bad.erl",[{_,_,_}|_]}],_} = |
| 416 | + compile:string("-module(bad). f( ->", |
| 417 | + [return_errors, {source, "bad.erl"}]), |
| 418 | + |
| 419 | + %% Cover: option not in a list (undocumented feature). |
| 420 | + {ok,smod,_} = compile:string("-module(smod). -export([f/0]). f() -> ok.", binary), |
| 421 | + |
| 422 | + %% noenv_string/2. |
| 423 | + {ok,nmod,_} = compile:noenv_string( |
| 424 | + "-module(nmod). -export([f/0]). f() -> ok.", []), |
| 425 | + |
| 426 | + %% include_path_open: include from in-memory files. |
| 427 | + Headers = #{ |
| 428 | + "my_header.hrl" => |
| 429 | + <<"-record(point, {x, y}).\n" |
| 430 | + "-define(ORIGIN, #point{x=0, y=0}).\n">> |
| 431 | + }, |
| 432 | + PathOpen = fun(_Path, Name, _Modes) -> |
| 433 | + case maps:find(Name, Headers) of |
| 434 | + {ok, Content} -> |
| 435 | + {ok, Fd} = file:open(Content, [ram, read, binary, cooked]), |
| 436 | + {ok, Fd, Name}; |
| 437 | + error -> |
| 438 | + {error, enoent} |
| 439 | + end |
| 440 | + end, |
| 441 | + {ok,incmod,BinInc} = compile:string( |
| 442 | + "-module(incmod).\n" |
| 443 | + "-include(\"my_header.hrl\").\n" |
| 444 | + "-export([f/0]).\n" |
| 445 | + "f() -> ?ORIGIN.\n", |
| 446 | + [{include_path_open, PathOpen}]), |
| 447 | + {module,incmod} = code:load_binary(incmod, "incmod.erl", BinInc), |
| 448 | + {point,0,0} = incmod:f(), |
| 449 | + true = code:delete(incmod), |
| 450 | + false = code:purge(incmod), |
| 451 | + |
| 452 | + %% include_path_open: nested includes from in-memory files. |
| 453 | + Headers2 = #{ |
| 454 | + "types.hrl" => |
| 455 | + <<"-type my_int() :: integer().\n">>, |
| 456 | + "all.hrl" => |
| 457 | + <<"-include(\"types.hrl\").\n" |
| 458 | + "-define(DEFAULT, 0).\n">> |
| 459 | + }, |
| 460 | + PathOpen2 = fun(_Path, Name, _Modes) -> |
| 461 | + case maps:find(Name, Headers2) of |
| 462 | + {ok, Content} -> |
| 463 | + {ok, Fd} = file:open(Content, [ram, read, binary, cooked]), |
| 464 | + {ok, Fd, Name}; |
| 465 | + error -> |
| 466 | + {error, enoent} |
| 467 | + end |
| 468 | + end, |
| 469 | + {ok,nestmod,BinNest} = compile:string( |
| 470 | + "-module(nestmod).\n" |
| 471 | + "-include(\"all.hrl\").\n" |
| 472 | + "-export([f/0]).\n" |
| 473 | + "-spec f() -> my_int().\n" |
| 474 | + "f() -> ?DEFAULT.\n", |
| 475 | + [{include_path_open, PathOpen2}]), |
| 476 | + {module,nestmod} = code:load_binary(nestmod, "nestmod.erl", BinNest), |
| 477 | + 0 = nestmod:f(), |
| 478 | + true = code:delete(nestmod), |
| 479 | + false = code:purge(nestmod), |
| 480 | + |
| 481 | + %% include_path_open: missing include returns error. |
| 482 | + PathOpenNone = fun(_Path, _Name, _Modes) -> {error, enoent} end, |
| 483 | + {error, _, _} = compile:string( |
| 484 | + "-module(missinc).\n" |
| 485 | + "-include(\"nonexistent.hrl\").\n" |
| 486 | + "-export([f/0]).\n" |
| 487 | + "f() -> ok.\n", |
| 488 | + [{include_path_open, PathOpenNone}, return_errors]), |
| 489 | + |
| 490 | + ok. |
| 491 | + |
329 | 492 | module_mismatch(Config) when is_list(Config) -> |
330 | 493 | DataDir = proplists:get_value(data_dir, Config), |
331 | 494 | File = filename:join(DataDir, "wrong_module_name.erl"), |
|
0 commit comments