SNAPKITTYWEST commited on
Commit
b1f2b40
·
verified ·
1 Parent(s): 129e72e

Add test/hk_search_job_tests.erl

Browse files
Files changed (1) hide show
  1. test/hk_search_job_tests.erl +68 -0
test/hk_search_job_tests.erl ADDED
@@ -0,0 +1,68 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ %%%-------------------------------------------------------------------
2
+ %%% @doc Covers "search orchestration" from `<test>': runs the full
3
+ %%% `<search_pipeline>' end-to-end against the bundled mock provider
4
+ %%% (no network required) and asserts every stage's event fires, in
5
+ %%% pipeline order, and the job reaches `done' with synthesized
6
+ %%% results.
7
+ %%% @end
8
+ %%%-------------------------------------------------------------------
9
+ -module(hk_search_job_tests).
10
+ -include_lib("eunit/include/eunit.hrl").
11
+
12
+ setup() -> hk_test_helper:start_app().
13
+ teardown(Ok) -> hk_test_helper:stop_app(Ok).
14
+
15
+ search_fixture_test_() ->
16
+ {timeout, 20, {setup, fun setup/0, fun teardown/1, fun(_) -> [
17
+ {"a search job runs every pipeline stage in order and completes",
18
+ fun full_pipeline_runs_in_order/0}
19
+ ] end}}.
20
+
21
+ full_pipeline_runs_in_order() ->
22
+ ok = hk_event_bus:subscribe(#{category_prefix => <<"search.">>}),
23
+ {ok, JobId} = hk_search:start(undefined, <<"erlang otp supervision">>, #{max_iterations => 2}),
24
+ Categories = collect_until(<<"search.completed">>, JobId, [], 10000),
25
+ ok = hk_event_bus:unsubscribe(),
26
+
27
+ ?assertEqual(<<"search.started">>, hd(Categories)),
28
+ ?assertEqual(<<"search.completed">>, lists:last(Categories)),
29
+ %% The pipeline stage events must appear in the same relative order
30
+ %% every time (deterministic orchestration) -- assert each of these
31
+ %% appears, and that it appears before the next one in the list.
32
+ ExpectedOrder = [<<"search.started">>, <<"search.query_generated">>,
33
+ <<"search.provider_called">>, <<"search.results_received">>,
34
+ <<"search.urls_deduplicated">>, <<"search.document_retrieved">>,
35
+ <<"search.result_synthesized">>, <<"search.completed">>],
36
+ assert_relative_order(ExpectedOrder, Categories),
37
+
38
+ {ok, Pid} = hk_search_registry:lookup(JobId),
39
+ {ok, Result} = hk_search_job:await_result(Pid, 1000),
40
+ ?assert(maps:is_key(results, Result)),
41
+ ?assert(maps:is_key(sources, Result)).
42
+
43
+ %%% internal
44
+
45
+ collect_until(TargetCategory, JobId, Acc, TimeoutMs) ->
46
+ receive
47
+ {hk_event, #{category := TargetCategory, data := #{job_id := JobId}}} ->
48
+ lists:reverse([TargetCategory | Acc]);
49
+ {hk_event, #{category := Cat, data := #{job_id := JobId}}} ->
50
+ collect_until(TargetCategory, JobId, [Cat | Acc], TimeoutMs);
51
+ {hk_event, _Other} ->
52
+ collect_until(TargetCategory, JobId, Acc, TimeoutMs)
53
+ after TimeoutMs ->
54
+ lists:reverse(Acc)
55
+ end.
56
+
57
+ assert_relative_order([_Last], _Categories) ->
58
+ ok;
59
+ assert_relative_order([A, B | Rest], Categories) ->
60
+ IdxA = index_of(A, Categories),
61
+ IdxB = index_of(B, Categories),
62
+ ?assert(IdxA =/= not_found andalso IdxB =/= not_found andalso IdxA < IdxB),
63
+ assert_relative_order([B | Rest], Categories).
64
+
65
+ index_of(X, List) -> index_of(X, List, 1).
66
+ index_of(_X, [], _N) -> not_found;
67
+ index_of(X, [X | _], N) -> N;
68
+ index_of(X, [_ | T], N) -> index_of(X, T, N + 1).