File 4321-ct-Add-callback-attribute-to-ct_hooks.patch of Package erlang
From b2c9e23803ca3d26b46e205626bdc20c065e04d7 Mon Sep 17 00:00:00 2001
From: Lukas Larsson <lukas@erlang.org>
Date: Wed, 27 Sep 2023 16:01:28 +0200
Subject: [PATCH 1/2] ct: Add callback attribute to ct_hooks
---
lib/common_test/src/Makefile | 6 +-
lib/common_test/src/ct_hooks.erl | 291 +++++++++++++++++++++++
lib/common_test/src/cth_conn_log.erl | 2 +
lib/common_test/src/cth_log_redirect.erl | 3 +-
lib/common_test/src/cth_surefire.erl | 11 +-
5 files changed, 308 insertions(+), 5 deletions(-)
diff --git a/lib/common_test/src/Makefile b/lib/common_test/src/Makefile
index 00f13589f3..6e84601c18 100644
--- a/lib/common_test/src/Makefile
+++ b/lib/common_test/src/Makefile
@@ -41,7 +41,7 @@ RELSYSDIR = $(RELEASE_PATH)/lib/common_test-$(VSN)
# ----------------------------------------------------
BEHAVIOUR_MODULES= \
- ct_suite
+ ct_suite ct_hooks
MODULES= \
ct \
@@ -70,7 +70,6 @@ MODULES= \
ct_config_plain \
ct_config_xml \
ct_slave \
- ct_hooks\
ct_hooks_lock\
cth_log_redirect\
cth_surefire \
@@ -172,3 +171,6 @@ release_docs_spec: docs
# Include dependencies -- list below added by Kostis Sagonas
$(EBIN)/cth_log_redirect.beam: ../../kernel/include/logger.hrl ../../kernel/src/logger_internal.hrl
+$(EBIN)/cth_log_redirect.beam: ../ebin/ct_hooks.beam
+$(EBIN)/cth_conn_log.beam: ../ebin/ct_hooks.beam
+$(EBIN)/cth_surefire.beam: ../ebin/ct_hooks.beam
diff --git a/lib/common_test/src/ct_hooks.erl b/lib/common_test/src/ct_hooks.erl
index d182e08efc..615ca164f8 100644
--- a/lib/common_test/src/ct_hooks.erl
+++ b/lib/common_test/src/ct_hooks.erl
@@ -43,6 +43,297 @@
-record(ct_hook_config, {id, module, prio, scope, opts = [],
state = [], groups = []}).
+%% -------------------------------------------------------------------------
+%% Callbacks
+%% -------------------------------------------------------------------------
+-callback id(Opts) -> Id when Opts :: term(), Id :: term().
+
+-callback init(Id, Opts) -> {ok, State} | {ok, State, Priority} when
+ Id :: reference() | term(),
+ Opts :: term(),
+ State :: term(),
+ Priority :: integer().
+
+-callback on_tc_skip(SuiteName, TestName, Reason, CTHState) -> NewCTHState when
+ SuiteName :: atom(),
+ TestName :: init_per_suite | end_per_suite |
+ {init_per_group, GroupName} |
+ {end_per_group, GroupName} |
+ {FuncName, GroupName} |
+ FuncName,
+ FuncName :: atom(),
+ GroupName :: atom(),
+ Reason :: {tc_auto_skip | tc_user_skip, term()},
+ CTHState :: term(),
+ NewCTHState :: term().
+
+-callback on_tc_fail(SuiteName, TestName, Reason, CTHState) -> NewCTHState when
+ SuiteName :: atom(),
+ TestName :: init_per_suite | end_per_suite |
+ {init_per_group, GroupName} |
+ {end_per_group, GroupName} |
+ {FuncName, GroupName} |
+ FuncName,
+ FuncName :: atom(),
+ GroupName :: atom(),
+ Reason :: term(),
+ CTHState :: term(),
+ NewCTHState :: term().
+
+-callback post_end_per_suite(SuiteName, Config, Return, CTHState) -> Result when
+ SuiteName :: atom(),
+ Config :: [{Key,Value}],
+ Return :: Config | SkipOrFail | term(),
+ NewReturn :: Config | SkipOrFail | term(),
+ SkipOrFail :: {fail,Reason} | {skip, Reason},
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewReturn, NewCTHState},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback pre_end_per_suite(SuiteName, EndData, CTHState) -> Result when
+ SuiteName :: atom(),
+ EndData :: Config | SkipOrFail,
+ Config :: [{Key, Value}],
+ NewConfig :: [{Key, Value}],
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewConfig | SkipOrFail,
+ NewCTHState},
+ SkipOrFail :: {fail, Reason} | {skip, Reason},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback post_end_per_group(SuiteName, GroupName, Config, Return, CTHState) -> Result when
+ SuiteName :: atom(),
+ GroupName :: atom(),
+ Config :: [{Key, Value}],
+ Return :: Config | SkipOrFail | term(),
+ NewReturn :: Config | SkipOrFail | term(),
+ SkipOrFail :: {fail, Reason} | {skip, Reason},
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewReturn, NewCTHState},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback pre_end_per_group(SuiteName, GroupName, EndData, CTHState) -> Result when
+ SuiteName :: atom(),
+ GroupName :: atom(),
+ EndData :: Config | SkipOrFail,
+ Config :: [{Key, Value}],
+ NewConfig :: [{Key, Value}],
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewConfig | SkipOrFail, NewCTHState},
+ SkipOrFail :: {fail, Reason} | {skip, Reason},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback post_end_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState) -> Result when
+ SuiteName :: atom(),
+ TestcaseName :: atom(),
+ Config :: [{Key, Value}],
+ Return :: Config | SkipOrFail | term(),
+ NewReturn :: Config | SkipOrFail | term(),
+ SkipOrFail :: {fail, Reason} |
+ {skip, Reason},
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewReturn, NewCTHState},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback pre_end_per_testcase(SuiteName, TestcaseName, EndData, CTHState) -> Result when
+ SuiteName :: atom(),
+ TestcaseName :: atom(),
+ EndData :: Config,
+ Config :: [{Key, Value}],
+ NewConfig :: [{Key, Value}],
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewConfig, NewCTHState},
+ Key :: atom(),
+ Value :: term().
+
+-callback post_init_per_testcase(SuiteName, TestcaseName, Config, Return, CTHState) -> Result when
+ SuiteName :: atom(),
+ TestcaseName :: atom(),
+ Config :: [{Key, Value}],
+ Return :: Config | SkipOrFail | term(),
+ NewReturn :: Config | SkipOrFail | term(),
+ SkipOrFail :: {fail, Reason} |
+ {skip, Reason},
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewReturn, NewCTHState},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback pre_init_per_testcase(SuiteName, TestcaseName, InitData, CTHState) -> Result when
+ SuiteName :: atom(),
+ TestcaseName :: atom(),
+ InitData :: Config | SkipOrFail,
+ Config :: [{Key, Value}],
+ NewConfig :: [{Key, Value}],
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewConfig | SkipOrFail, NewCTHState},
+ SkipOrFail :: {fail, Reason} |
+ {skip, Reason},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback post_init_per_group(SuiteName, GroupName, Config, Return, CTHState) -> Result when
+ SuiteName :: atom(),
+ GroupName :: atom(),
+ Config :: [{Key, Value}],
+ Return :: Config | SkipOrFail | term(),
+ NewReturn :: Config | SkipOrFail | term(),
+ SkipOrFail :: {fail, Reason} | {skip, Reason},
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewReturn, NewCTHState},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback pre_init_per_group(SuiteName, GroupName, InitData, CTHState) -> Result when
+ SuiteName :: atom(),
+ GroupName :: atom(),
+ InitData :: Config | SkipOrFail,
+ Config :: [{Key, Value}],
+ NewConfig :: [{Key, Value}],
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewConfig | SkipOrFail,
+ NewCTHState},
+ SkipOrFail :: {fail, Reason} | {skip, Reason},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback post_init_per_suite(SuiteName, Config, Return, CTHState) -> Result when
+ SuiteName :: atom(),
+ Config :: [{Key, Value}],
+ Return :: Config | SkipOrFail | term(),
+ NewReturn :: Config | SkipOrFail | term(),
+ SkipOrFail :: {fail, Reason} |
+ {skip, Reason} |
+ term(),
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {NewReturn, NewCTHState},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback pre_init_per_suite(SuiteName, InitData, CTHState) -> Result when
+ SuiteName :: atom(),
+ InitData :: Config | SkipOrFail,
+ Config :: [{Key, Value}],
+ NewConfig :: [{Key, Value}],
+ CTHState :: term(),
+ NewCTHState :: term(),
+ Result :: {Return, NewCTHState},
+ Return :: NewConfig | SkipOrFail,
+ SkipOrFail :: {fail, Reason} | {skip, Reason},
+ Key :: atom(),
+ Value :: term(),
+ Reason :: term().
+
+-callback post_all(SuiteName, Return, GroupDefs) -> NewReturn when
+ SuiteName :: atom(),
+ Return :: Tests | {skip, Reason},
+ NewReturn :: Tests | {skip, Reason},
+ Tests :: [TestCase |
+ {testcase, TestCase, TCRepeatProps} |
+ {group, GroupName} |
+ {group, GroupName, Properties} |
+ {group, GroupName, Properties, SubGroups}],
+ TestCase :: atom(),
+ TCRepeatProps :: [{repeat, N} |
+ {repeat_until_ok, N} |
+ {repeat_until_fail, N}],
+ GroupName :: atom(),
+ Properties :: GroupProperties | default,
+ SubGroups :: [{GroupName, Properties} |
+ {GroupName, Properties, SubGroups}],
+ Shuffle :: shuffle | {shuffle, Seed},
+ Seed :: {integer(), integer(), integer()},
+ GroupRepeatType ::
+ repeat | repeat_until_all_ok |
+ repeat_until_all_fail |
+ repeat_until_any_ok |
+ repeat_until_any_fail,
+ N :: integer() | forever,
+ GroupDefs :: [Group],
+ Group ::
+ {GroupName, GroupProperties,
+ GroupsAndTestCases},
+ GroupProperties ::
+ [parallel | sequence | Shuffle |
+ {GroupRepeatType, N}],
+ GroupsAndTestCases ::
+ [Group | {group, GroupName} | TestCase],
+ Reason :: term().
+
+-callback post_groups(SuiteName, GroupDefs) -> NewGroupDefs when
+ SuiteName :: atom(),
+ GroupDefs :: [Group],
+ NewGroupDefs :: [Group],
+ Group ::
+ {GroupName, Properties,
+ GroupsAndTestCases},
+ GroupName :: atom(),
+ Properties :: [parallel | sequence | Shuffle | {GroupRepeatType, N}],
+ GroupsAndTestCases :: [Group |
+ {group, GroupName} |
+ TestCase |
+ {testcase, TestCase, TCRepeatProps}],
+ TestCase :: atom(),
+ TCRepeatProps :: [{repeat, N} |
+ {repeat_until_ok, N} |
+ {repeat_until_fail, N}],
+ Shuffle :: shuffle | {shuffle, Seed},
+ Seed :: {integer(), integer(), integer()},
+ GroupRepeatType ::
+ repeat | repeat_until_all_ok |
+ repeat_until_all_fail |
+ repeat_until_any_ok |
+ repeat_until_any_fail,
+ N :: integer() | forever.
+
+-callback terminate(CTHState) -> term() when CTHState :: term().
+
+-optional_callbacks(
+ [id/1,
+ on_tc_fail/4,
+ on_tc_skip/4,
+ post_all/3,
+ post_end_per_group/5,
+ post_end_per_suite/4,
+ post_end_per_testcase/5,
+ post_groups/2,
+ post_init_per_group/5,
+ post_init_per_suite/4,
+ post_init_per_testcase/5,
+ pre_end_per_group/4,
+ pre_end_per_suite/3,
+ pre_end_per_testcase/4,
+ pre_init_per_group/4,
+ pre_init_per_suite/3,
+ pre_init_per_testcase/4,
+ terminate/1]).
+
%% -------------------------------------------------------------------------
%% API Functions
%% -------------------------------------------------------------------------
diff --git a/lib/common_test/src/cth_conn_log.erl b/lib/common_test/src/cth_conn_log.erl
index 744642c69f..fd76179306 100644
--- a/lib/common_test/src/cth_conn_log.erl
+++ b/lib/common_test/src/cth_conn_log.erl
@@ -57,6 +57,8 @@
pre_init_per_testcase/4,
post_end_per_testcase/5]).
+-behaviour(ct_hooks).
+
%%----------------------------------------------------------------------
%% Type declarations
%%----------------------------------------------------------------------
diff --git a/lib/common_test/src/cth_log_redirect.erl b/lib/common_test/src/cth_log_redirect.erl
index 04e964f51a..f51cfd4bc6 100644
--- a/lib/common_test/src/cth_log_redirect.erl
+++ b/lib/common_test/src/cth_log_redirect.erl
@@ -44,6 +44,7 @@
-include("../../kernel/src/logger_internal.hrl").
-behaviour(gen_server).
+-behaviour(ct_hooks).
-record(eh_state, {log_func,
curr_suite,
@@ -58,7 +59,7 @@ id(_Opts) ->
init(?MODULE, _Opts) ->
ct_util:mark_process(),
ok = start_log_handler(),
- tc_log_async.
+ {ok, tc_log_async}.
pre_init_per_suite(Suite, Config, State) ->
set_curr_func({Suite,init_per_suite}, Config),
diff --git a/lib/common_test/src/cth_surefire.erl b/lib/common_test/src/cth_surefire.erl
index 578bdd6163..1f449ae809 100644
--- a/lib/common_test/src/cth_surefire.erl
+++ b/lib/common_test/src/cth_surefire.erl
@@ -47,7 +47,10 @@
-export([terminate/1]).
%% Gen server callbacks
--export([init/1, handle_call/3]).
+-export([init/1, handle_call/3, handle_cast/2]).
+
+-behaviour(gen_server).
+-behaviour(ct_hooks).
-record(state, { filepath, axis, properties, package, hostname,
curr_suite, curr_suite_file, curr_suite_ast, curr_suite_ts, curr_group = [],
@@ -76,7 +79,7 @@
%% the execution time of diameter_traffic_SUITE from 30 min to 5 min.
init(Path, Opts) ->
{ok, Pid} = gen_server:start(?MODULE, [Path, Opts], []),
- Pid.
+ {ok, Pid}.
init([Path, Opts]) ->
ct_util:mark_process(),
@@ -101,6 +104,10 @@ handle_call({Function, Args}, _From, State) ->
{Reply,NewState} = apply(?MODULE, Function, Args ++ [State]),
{reply,Reply,NewState}.
+%% Ignore any cast
+handle_cast(_What, State) ->
+ {noreply, State}.
+
id(Opts) ->
case proplists:get_value(path, Opts) of
undefined -> ?default_report;
--
2.35.3