How will the callers know the callbacks defined in ct_netconfc w/o being declared as behaviour?

We all know that in order to implement a module based on a behaviour say gen_server, we need to declare the module as gen_server behavior and implement the following callbacks.


%% gen_server callbacks

ct_netconfc has defined a few ct-gen_conn callbacks without declaring any behaviour. Why is it? How will ct_gen_conn know that it has to call these callbacks?


%% ct_gen_conn callbacks

Similarly, ct_netconfc has defined a few ct_conn_log callbacks without declaring any behaviour.

%% ct_conn_log callback

Another query; who calls ct_netconfc:close? Is it ct_util_server as per code comment?

%% Called by ct_util_server to close registered connections before terminate.
close(Client) ->
    case get_handle(Client) of
	{ok,Pid} ->
	%% ......
1 Like

Please have a look at

It is written It is possible to specify, it does not suggest you can’t have function callbacks in code without the behavior concept.

If you grep “Mod:” in ct_gen_conn module, you will get something like this:

7 matches for “Mod:” in buffer: ct_gen_conn.erl
381: try Mod:init(Name, Addr, InitData) of
421: {Reply, NewState} = Mod:handle_msg(Msg, State),
428: {Reply, NewState} = Mod:handle_msg(Msg, State),
434: case Mod:handle_msg(Msg, From, State) of
487: case Mod:handle_msg(Msg, State) of
511: Mod:terminate(Pid, State);
524: Mod:reconnect(Addr, State).

Those lines will try to call functions in a module found in Mod variable. Behaviors are not needed for that. This will be done in the runtime.

Function names are hardcoded and they’re kind of a contract between generic and specific code implementing the callbacks.

Behavior concept can be seen as a way of officially specifying the contract (and the behavior) to make it easier if someone is not fluent with generic part - so for example you can get a nice warnings when some of the callbacks were not implemented.

You can read more here: Clients and Servers | Learn You Some Erlang for Great Good!
I recommend writing your own behavior as described there - it is a great exercise to understand how it works and might be useful in future.

I would speculate it is ct_util module:

lib/common_test/src/ct_util.erl: catch CB:close(Pid),
lib/common_test/src/ct_util.erl: CB:close(Handle),