summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/horse.app.src24
-rw-r--r--src/horse.erl49
-rw-r--r--src/horse_autoexport.erl60
3 files changed, 133 insertions, 0 deletions
diff --git a/src/horse.app.src b/src/horse.app.src
new file mode 100644
index 0000000..6ab0339
--- /dev/null
+++ b/src/horse.app.src
@@ -0,0 +1,24 @@
+%% Copyright (c) 2013, Loïc Hoguin <[email protected]>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+{application, horse, [
+ {description, "Integrated performance testing."},
+ {vsn, "0.1.0"},
+ {modules, []},
+ {registered, []},
+ {applications, [
+ kernel,
+ stdlib
+ ]}
+]}.
diff --git a/src/horse.erl b/src/horse.erl
new file mode 100644
index 0000000..b03a05b
--- /dev/null
+++ b/src/horse.erl
@@ -0,0 +1,49 @@
+%% Copyright (c) 2013, Loïc Hoguin <[email protected]>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(horse).
+
+-export([app_perf/1]).
+-export([mod_perf/1]).
+
+%% These might be interesting later on.
+%% @todo horse_init, horse_end
+%% @todo horse_init_per_test, horse_end_per_test
+
+app_perf(App) when is_atom(App) ->
+ io:format("Running horse on application ~s~n", [App]),
+ ok = application:load(App),
+ {ok, Modules} = application:get_key(App, modules),
+ _ = [mod_perf(M) || M <- lists:sort(Modules)],
+ ok.
+
+mod_perf(Mod) when is_atom(Mod) ->
+ Perfs = [F || {F, 0} <- Mod:module_info(exports),
+ "horse_" =:= string:substr(atom_to_list(F), 1, 6)],
+ _ = [fun_perf(Mod, Fun) || Fun <- Perfs],
+ ok.
+
+fun_perf(Mod, Fun) when is_atom(Mod), is_atom(Fun) ->
+ %% Dry run.
+ _ = Mod:Fun(),
+ %% Proper run.
+ Before = os:timestamp(),
+ _Val = Mod:Fun(),
+ After = os:timestamp(),
+ %% Results.
+ Time = timer:now_diff(After, Before),
+ "horse_" ++ Name = atom_to_list(Fun),
+ io:format("~s:~s in ~b.~6.10.0bs~n",
+ [Mod, Name, Time div 1000000, Time rem 1000000]),
+ ok.
diff --git a/src/horse_autoexport.erl b/src/horse_autoexport.erl
new file mode 100644
index 0000000..6e4a49a
--- /dev/null
+++ b/src/horse_autoexport.erl
@@ -0,0 +1,60 @@
+%% Copyright (c) 2013, Loïc Hoguin <[email protected]>
+%%
+%% Permission to use, copy, modify, and/or distribute this software for any
+%% purpose with or without fee is hereby granted, provided that the above
+%% copyright notice and this permission notice appear in all copies.
+%%
+%% THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+%% WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+%% MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+%% ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+%% WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+%% ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+%% OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+
+-module(horse_autoexport).
+
+-export([parse_transform/2]).
+
+parse_transform([File, Module|Forms], _) ->
+ Exports = [F || {attribute, _, export, [{F, 0}]} <- Forms],
+ AutoExports = [{attribute, 0, export, [{F, 0}]}
+ || {function, _, F, 0, _} <- Forms,
+ "horse_" =:= string:substr(atom_to_list(F), 1, 6),
+ false =:= lists:member(F, Exports)],
+ replace_calls([File, Module|AutoExports ++ Forms]).
+
+replace_calls(Forms) ->
+ lists:flatten([replace_call(Form) || Form <- Forms]).
+
+replace_call(
+ {function, Fu, Name, 0, [
+ {clause, Cl, [], [], [
+ {call, Ca, {remote, _, {atom, _, horse}, {atom, _, repeat}}, [
+ Repeat,
+ Expr
+ ]}
+ ]}
+ ]}
+) when Repeat > 0 ->
+ GenName = list_to_atom("generated_" ++ atom_to_list(Name)),
+ [
+ {function, Fu, Name, 0, [
+ {clause, Cl, [], [], [
+ {call, Ca, {atom, Ca, GenName}, [Repeat]}
+ ]}
+ ]},
+ {function, Ca, GenName, 1, [
+ {clause, Ca, [{integer, Ca, 0}], [], [
+ {atom, Ca, ok}
+ ]},
+ {clause, Ca, [{var, Ca, 'N'}], [], [
+ Expr,
+ {call, Ca, {atom, Ca, GenName}, [
+ {op, Ca, '-', {var, Ca, 'N'}, {integer, Ca, 1}}
+ ]}
+ ]}
+ ]}
+ ];
+replace_call(Form) ->
+ Form.