/test/erlv8_tests.erl

http://github.com/beamjs/erlv8 · Erlang · 132 lines · 97 code · 29 blank · 6 comment · 1 complexity · db0d89e60c1f5bc8b4d970e3436e2edd MD5 · raw file

  1. -module(erlv8_tests).
  2. -include_lib("proper/include/proper.hrl").
  3. -include_lib("eunit/include/eunit.hrl").
  4. -behaviour(proper_statem).
  5. -export([initial_state/0, command/1, precondition/2, postcondition/3,
  6. next_state/3]).
  7. -compile(export_all).
  8. -record(state, {
  9. vms = [],
  10. passed = []
  11. }).
  12. %% helpers
  13. start_vm() ->
  14. {ok, VM} = erlv8_vm:start(),
  15. VM.
  16. exit_vm(VM) ->
  17. erlv8_vm:stop(VM),
  18. VM.
  19. run_tests(VM) ->
  20. ets:insert(?MODULE, {vm, VM}),
  21. proper:module(?MODULE,
  22. [{'on_output',
  23. fun(Format, Data) ->
  24. io:format(standard_error, Format, Data)
  25. end},
  26. {numtests, 100}]).
  27. %% statem
  28. initial_state() ->
  29. #state{}.
  30. command(#state{ vms = VMs, passed = Passed }) ->
  31. frequency([
  32. {1 - (length(VMs) + length(Passed)), {call, ?MODULE, start_vm, []}},
  33. {length(Passed), {call, ?MODULE, exit_vm, [oneof(Passed)]}},
  34. {length(VMs), {call, ?MODULE, run_tests, [oneof(VMs)]}}
  35. ]).
  36. precondition(_State, _Call) ->
  37. true.
  38. postcondition(_S, {call, ?MODULE, run_tests, [_VM]}, []) ->
  39. true;
  40. postcondition(_S, {call, ?MODULE, run_tests, [_VM]}, _) ->
  41. false;
  42. postcondition(_S, _C, _R) ->
  43. true.
  44. next_state(#state{ vms = VMs } = State, V, {call, ?MODULE, start_vm, []}) ->
  45. State#state{ vms = [V|VMs] };
  46. next_state(#state{ passed = VMs } = State, _V, {call, ?MODULE, exit_vm, [VM]}) ->
  47. State#state{ passed = VMs -- [VM] };
  48. next_state(#state{ vms = VMs, passed = Passed } = State, _V, {call, ?MODULE, run_tests, [VM]}) ->
  49. State#state{ vms = VMs -- [VM], passed = [VM|Passed] };
  50. next_state(State, _V, _C) ->
  51. State.
  52. statem() ->
  53. ?FORALL(Cmds, commands(?MODULE),
  54. ?TRAPEXIT(
  55. begin
  56. {History,State,Result} = run_commands(?MODULE, Cmds),
  57. [ erlv8_vm:stop(VM) || VM <- State#state.vms ],
  58. ?WHENFAIL(io:format("History: ~p\nState: ~p\nResult: ~p\n",
  59. [History, State, Result]),
  60. aggregate(command_names(Cmds), Result =:= ok))
  61. end)).
  62. %%% generators
  63. js_string() ->
  64. oneof([list(proper_stdgen:utf8_char()),
  65. proper_stdgen:utf8_bin()]).
  66. %%% properties
  67. %% type conversion
  68. prop_to_js_string() ->
  69. ?FORALL(String, js_string(),
  70. begin
  71. [{vm, VM}] = ets:lookup(?MODULE, vm),
  72. Bin = unicode:characters_to_binary(String),
  73. Obj = erlv8_vm:taint(VM, Bin),
  74. case Obj =:= Bin of
  75. true ->
  76. ok;
  77. false ->
  78. io:format("->~p/~p~n", [Bin, Obj]),
  79. ok
  80. end,
  81. Obj =:= Bin
  82. end).
  83. %% eunit
  84. t_properties() ->
  85. ?assertEqual(true, proper:quickcheck(statem(),
  86. [{'on_output',
  87. fun(Format, Data) ->
  88. io:format(standard_error, Format, Data)
  89. end},
  90. {numtests, 10}])).
  91. erlv8_test_() ->
  92. [{setup,
  93. fun() ->
  94. ets:new(?MODULE,[named_table, public]),
  95. ok = application:start(erlv8)
  96. end,
  97. fun(_) ->
  98. ets:delete(?MODULE),
  99. application:stop(erlv8)
  100. end,
  101. [
  102. {timeout, 30, {"PropEr tests", ?_test(t_properties())}}
  103. ]}].