Also drop migration code now outdated.

* Add cacheless dmt_api tests
This commit is contained in:
Andrew Mayorov 2022-09-14 18:09:41 +03:00 committed by GitHub
parent 0453a67618
commit 5bbcf17aaa
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 179 deletions

View File

@ -10,7 +10,7 @@
{<<"cowlib">>,{pkg,<<"cowlib">>,<<"2.11.0">>},2},
{<<"damsel">>,
{git,"https://github.com/valitydev/damsel.git",
{ref,"53dab99962edf2dd0102a54e41133d91ccbcbef5"}},
{ref,"4e82c2431ae5d0045c7e21a29ed27f01f5b0f6d5"}},
0},
{<<"dmt_core">>,
{git,"https://github.com/valitydev/dmt-core.git",

View File

@ -1,7 +1,5 @@
-module(dmt_api_repository_migration).
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-export([migrate/2]).
-type snapshot() :: dmt_api_repository:snapshot().
@ -9,44 +7,10 @@
-type version() :: dmt_api_repository:version().
-spec migrate
(version(), commit()) -> commit();
(version(), snapshot()) -> snapshot().
migrate(1, Data) ->
migrate_legacy_payment_system_conditions(Data).
migrate_legacy_payment_system_conditions(Data) ->
% TODO OPS-161
% Relevant for https://github.com/valitydev/damsel/commit/09e7a75, revert this commit after
% complete migration.
% Replaces any `BankCardCondition` in a commit or snapshot which represents legacy payment
% system condition (i.e. one that compares against an atom in % `LegacyBankCardPaymentSystem`
% enum) with an empty `BankCardCondition`. Obviously, this incurs information loss yet
% significantly easier than proper mapping. Two reasons why this looks valid:
% - Production domain config do not contain legacy conditions anywhere in the last 3 months
% of snapshots.
% - https://github.com/valitydev/party-management since at least bb4549c won't handle them
% anyway.
genlib_ted:run(
fun
({AllAnyOf, PredicateSet}, _Annos) when AllAnyOf == all_of; AllAnyOf == any_of ->
% NOTE
% Reconstruct potentially broken set (e.g. with duplicate elements).
{replace, {AllAnyOf, ordsets:from_list(migrate_legacy_payment_system_conditions(PredicateSet))}};
(Condition = #domain_BankCardCondition{}, _Annos) ->
{replace, migrate_legacy_payment_system_condition(Condition)};
(_, _Annos) ->
proceed
end,
Data
).
migrate_legacy_payment_system_condition(Condition) ->
case Condition#domain_BankCardCondition.definition of
{payment_system_is, Legacy} ->
true = is_atom(Legacy),
Condition#domain_BankCardCondition{definition = undefined};
{_, _} ->
Condition;
undefined ->
Condition
end.
(version(), commit()) -> no_return();
(version(), snapshot()) -> no_return().
migrate(1, _Data) ->
% NOTE
% Migration of version 1 events is not possible anymore since
% https://github.com/valitydev/damsel/commit/4e82c243
error(noimpl).

View File

@ -276,16 +276,19 @@ get_version(_) ->
% Be aware, this function is being mocked in the testsuite.
2.
get_earliest_supported_version(_) ->
2.
encode_event_data(FmtVsn, {commit, CommitIn, Meta}) ->
% NOTE
% Ensure that outdated commit won't sneak in.
Commit = migrate(1, get_version(event), commit, CommitIn),
Commit = migrate(get_earliest_supported_version(event), get_version(event), commit, CommitIn),
{arr, [{str, <<"commit">>}, encode(commit, Commit), encode_commit_meta(FmtVsn, Meta)]}.
encode_commit_meta(_FmtVsn, #{snapshot := SnapshotIn}) ->
% NOTE
% Ensure that outdated snapshot won't sneak in.
Snapshot = migrate(1, get_version(event), snapshot, SnapshotIn),
Snapshot = migrate(get_earliest_supported_version(event), get_version(event), snapshot, SnapshotIn),
{obj, #{{str, <<"snapshot">>} => encode(snapshot, Snapshot)}};
encode_commit_meta(_FmtVsn, #{}) ->
{obj, #{}}.
@ -310,6 +313,10 @@ migrate(Vsn, TargetVsn, Type, Data) when Vsn < TargetVsn ->
ok = validate(Type, Migrated),
migrate(Vsn + 1, TargetVsn, Type, Migrated).
% NOTE
% Dialyzer correctly evaluates that this function will never be called.
% Left here for illustrative purposes. It will play its part next time fmtvsn is bumped.
-dialyzer({nowarn_function, [validate/2]}).
validate(T, V) ->
_ = encode(T, V),
ok.

View File

@ -2,18 +2,12 @@
-include_lib("stdlib/include/assert.hrl").
-include_lib("damsel/include/dmsl_domain_thrift.hrl").
-include_lib("damsel/include/dmsl_domain_conf_thrift.hrl").
-export([all/0]).
-export([init_per_suite/1]).
-export([end_per_suite/1]).
-export([init_per_testcase/2]).
-export([end_per_testcase/2]).
-export([fv2_migration_succeeds/1]).
-export([fv2_modernization_succeeds/1]).
-type config() :: [{atom(), term()}].
-type test_case_name() :: atom().
@ -26,8 +20,9 @@
-spec all() -> [test_case_name()].
all() ->
[
fv2_migration_succeeds,
fv2_modernization_succeeds
% NOTE
% Migration of version 1 events is not testable anymore since
% https://github.com/valitydev/damsel/commit/4e82c243
].
-spec init_per_suite(config()) -> config().
@ -79,115 +74,3 @@ mk_rpc_id(Name) ->
-spec end_per_testcase(test_case_name(), config()) -> _.
end_per_testcase(_, _) ->
ok.
%%
-define(FMT_VSN_INITIAL, 1).
-define(FMT_VSN_TARGET, 2).
-define(LEGACY_CONDITION,
{payment_tool,
{bank_card, #domain_BankCardCondition{
definition = {payment_system_is, uzcard}
}}}
).
-define(TARGET_CONDITION,
{payment_tool,
{bank_card, #domain_BankCardCondition{
definition = undefined
}}}
).
-spec fv2_migration_succeeds(config()) -> _.
fv2_migration_succeeds(C) ->
ClientOpts = ?CONF(dmt_client_opts, C),
ok = meck:new(dmt_api_repository_v5, [passthrough]),
ok = meck:expect(dmt_api_repository_v5, get_version, fun(_) -> ?FMT_VSN_INITIAL end),
Version1 = get_latest_version(ClientOpts),
ObjectRef1 = #domain_CriterionRef{id = dmt_ct_helper:next_id()},
Commit1 = dmt_ct_helper:mk_insert_commit(
{criterion, #domain_CriterionObject{
ref = ObjectRef1,
data = #domain_Criterion{
name = <<"Legacy Criterion 1">>,
predicate = {condition, ?LEGACY_CONDITION}
}
}}
),
Version2 = dmt_client_api:commit(Version1, Commit1, ClientOpts),
ok = meck:expect(dmt_api_repository_v5, get_version, fun(_) -> ?FMT_VSN_TARGET end),
Snapshot2 = checkout(Version2, ClientOpts),
?assertMatch(
{criterion, #domain_CriterionObject{
data = #domain_Criterion{
predicate = {condition, ?TARGET_CONDITION}
}
}},
get_domain_object({criterion, ObjectRef1}, Snapshot2)
),
ObjectRef2 = #domain_CriterionRef{id = dmt_ct_helper:next_id()},
Commit2 = dmt_ct_helper:mk_insert_commit(
{criterion, #domain_CriterionObject{
ref = ObjectRef2,
data = #domain_Criterion{
name = <<"Legacy Criterion 2">>,
predicate = {condition, ?LEGACY_CONDITION}
}
}}
),
Version3 = dmt_client_api:commit(Version2, Commit2, ClientOpts),
Snapshot3 = checkout(Version3, ClientOpts),
?assertMatch(
{criterion, #domain_CriterionObject{
data = #domain_Criterion{
predicate = {condition, ?TARGET_CONDITION}
}
}},
get_domain_object({criterion, ObjectRef2}, Snapshot3)
),
ok = meck:unload(dmt_api_repository_v5).
-spec fv2_modernization_succeeds(config()) -> _.
fv2_modernization_succeeds(C) ->
ClientOpts = ?CONF(dmt_client_opts, C),
ok = meck:new(dmt_api_repository_v5, [passthrough]),
ok = meck:expect(dmt_api_repository_v5, get_version, fun(_) -> ?FMT_VSN_INITIAL end),
Version1 = get_latest_version(ClientOpts),
ObjectRef = #domain_CriterionRef{id = dmt_ct_helper:next_id()},
Commit = dmt_ct_helper:mk_insert_commit(
{criterion, #domain_CriterionObject{
ref = ObjectRef,
data = #domain_Criterion{
name = <<"Legacy Criterion">>,
predicate = {condition, ?LEGACY_CONDITION}
}
}}
),
Version2 = dmt_client_api:commit(Version1, Commit, #{}),
ok = meck:expect(dmt_api_repository_v5, get_version, fun(_) -> ?FMT_VSN_TARGET end),
ok = dmt_api_repository_v5:modernize(?CONF(woody_ctx, C)),
Snapshot2 = checkout(Version2, ClientOpts),
?assertMatch(
{criterion, #domain_CriterionObject{
data = #domain_Criterion{
predicate = {condition, ?TARGET_CONDITION}
}
}},
get_domain_object({criterion, ObjectRef}, Snapshot2)
),
ok = meck:unload(dmt_api_repository_v5).
%%
checkout(head, ClientOpts) ->
dmt_client_api:checkout({head, #domain_conf_Head{}}, ClientOpts);
checkout(Version, ClientOpts) when is_integer(Version) ->
dmt_client_api:checkout({version, Version}, ClientOpts).
get_latest_version(ClientOpts) ->
Snapshot = checkout(head, ClientOpts),
Snapshot#domain_conf_Snapshot.version.
get_domain_object(ObjectRef, #domain_conf_Snapshot{domain = Domain}) ->
maps:get(ObjectRef, Domain).

View File

@ -44,6 +44,7 @@
all() ->
[
{group, basic_lifecycle_v5},
{group, cacheless_lifecycle},
{group, repository_client}
].
@ -56,6 +57,11 @@ groups() ->
{group, error_mapping},
retry_commit
]},
{cacheless_lifecycle, [sequence], [
pull_commit,
{group, basic_lifecycle},
retry_commit
]},
{basic_lifecycle, [sequence, {repeat, 10}, shuffle], [
insert,
update,
@ -90,23 +96,33 @@ end_per_suite(C) ->
-spec init_per_group(group_name(), config()) -> config().
init_per_group(basic_lifecycle_v5, C) ->
[{group_apps, start_with_repository(dmt_api_repository_v5) ++ start_client()} | C];
Apps = start_dmt_api([{repository, dmt_api_repository_v5}]),
[{group_apps, Apps ++ start_client()} | C];
init_per_group(cacheless_lifecycle, C) ->
Apps = start_dmt_api([
{repository, dmt_api_repository_v5},
{max_cache_size, 0}
]),
[{group_apps, Apps ++ start_client()} | C];
init_per_group(repository_client, C) ->
[{group_apps, start_with_repository(dmt_api_repository_v5) ++ start_client()} | C];
Apps = start_dmt_api([{repository, dmt_api_repository_v5}]),
[{group_apps, Apps ++ start_client()} | C];
init_per_group(_, C) ->
C.
start_with_repository(Repository) ->
genlib_app:start_application_with(dmt_api, [
{repository, Repository},
{services, #{
automaton => #{
url => "http://machinegun:8022/v1/automaton"
}
}},
% 100Kb
{max_cache_size, 102400}
]).
start_dmt_api(Overrides) ->
genlib_app:start_application_with(
dmt_api,
[
{services, #{
automaton => #{
url => "http://machinegun:8022/v1/automaton"
}
}},
% 100Kb
{max_cache_size, 102400}
] ++ Overrides
).
start_client() ->
genlib_app:start_application_with(dmt_client, [
@ -127,6 +143,7 @@ start_client() ->
-spec end_per_group(group_name(), config()) -> term().
end_per_group(GroupName, C) when
GroupName == basic_lifecycle_v5;
GroupName == cacheless_lifecycle;
GroupName == repository_client
->
genlib_app:stop_unload_applications(?config(group_apps, C));