From daf6749c34f54d18296605edbe30ccd9dfa0fe0d Mon Sep 17 00:00:00 2001 From: Alice39s Date: Sun, 28 Jun 2026 05:17:59 +0900 Subject: [PATCH] fix(erlang): pass expected version to worker and fail fast on xdb mismatch --- binding/erlang/src/ip2region_sup.erl | 4 +-- binding/erlang/src/ip2region_worker.erl | 6 +++- binding/erlang/test/xdb_test.erl | 41 ++++++++++--------------- 3 files changed, 24 insertions(+), 27 deletions(-) diff --git a/binding/erlang/src/ip2region_sup.erl b/binding/erlang/src/ip2region_sup.erl index 05ad9db..7b07742 100644 --- a/binding/erlang/src/ip2region_sup.erl +++ b/binding/erlang/src/ip2region_sup.erl @@ -67,12 +67,12 @@ pool_child_specs() -> Acc end, [], DbConfig). -make_pool_spec(PoolName, _Version, File, PoolArgsCfg) -> +make_pool_spec(PoolName, Version, File, PoolArgsCfg) -> PoolArgs = [ {strategy, fifo}, {name, {local, PoolName}}, {worker_module, ip2region_worker} | PoolArgsCfg ], - WorkerArgs = [{xdb_file, File}], + WorkerArgs = [{xdb_file, File}, {expected_version, Version}], poolboy:child_spec(PoolName, PoolArgs, WorkerArgs). diff --git a/binding/erlang/src/ip2region_worker.erl b/binding/erlang/src/ip2region_worker.erl index 695c1b4..90d9152 100644 --- a/binding/erlang/src/ip2region_worker.erl +++ b/binding/erlang/src/ip2region_worker.erl @@ -62,10 +62,14 @@ init(Args) -> {ok, IoDevice} = file:open(XdbFileName, [read, binary]), {ok, HeaderBin} = file:read(IoDevice, ?XDB_HEADER_SIZE), {ok, Header} = ip2region_xdb:parse_header(HeaderBin), + ExpectedVersion = proplists:get_value(expected_version, Args), case resolve_version(Header) of - {ok, Version} -> + {ok, Version} when ExpectedVersion =:= undefined; ExpectedVersion =:= Version -> load_vector_index(IoDevice, Version), {ok, #state{xdb_fd = IoDevice, version = Version}}; + {ok, Version} -> + file:close(IoDevice), + {stop, {xdb_version_mismatch, ExpectedVersion, Version}}; {error, Reason} -> file:close(IoDevice), {stop, Reason} diff --git a/binding/erlang/test/xdb_test.erl b/binding/erlang/test/xdb_test.erl index aea2439..5388f6e 100644 --- a/binding/erlang/test/xdb_test.erl +++ b/binding/erlang/test/xdb_test.erl @@ -5,7 +5,7 @@ -define(IPV6_RESULT, "United States|Florida|Miami|Google LLC|US"). search_test_() -> - {ok, _} = application:ensure_all_started(ip2region), + {ok, _} = ip2region_test_util:start_app(), A = "中国|广东省|广州市|中国电信|CN", Region0 = xdb:search("1.0.8.0"), Region1 = xdb:search(<<"1.0.8.0">>), @@ -19,7 +19,7 @@ search_test_() -> ]. ipv6_search_test_() -> - setup_ipv6(), + {ok, _} = ip2region_test_util:start_app(), [ ?_assert(?IPV6_RESULT =:= xdb:search("2001:4860:4860::8888")), ?_assert(?IPV6_RESULT =:= xdb:search(<<"2001:4860:4860::8888">>)), @@ -27,7 +27,7 @@ ipv6_search_test_() -> ]. invalid_search_test_() -> - {ok, _} = application:ensure_all_started(ip2region), + {ok, _} = ip2region_test_util:start_app(), [ ?_assertEqual({error, bad_ip_format}, xdb:search("xxx.0.8.0")), ?_assertEqual({error, bad_ip_format}, xdb:search("::ggg")), @@ -35,27 +35,20 @@ invalid_search_test_() -> ]. ipv6_pool_not_configured_test() -> - try application:stop(ip2region) catch _:_ -> ok end, - try application:unload(ip2region) catch _:_ -> ok end, - ok = application:load(ip2region), - ok = application:set_env(ip2region, db, [{ipv4, "ip2region.xdb"}]), - {ok, _} = application:ensure_all_started(ip2region), + {ok, _} = ip2region_test_util:start_app([{ipv4, "ip2region.xdb"}]), ?assertEqual({error, pool_not_configured}, xdb:search("2001:4860:4860::8888")). -setup_ipv6() -> - try application:stop(ip2region) catch _:_ -> ok end, - try application:unload(ip2region) catch _:_ -> ok end, - ok = application:load(ip2region), - RepoRoot = repo_root(), - V6File = filename:join([RepoRoot, "data", "ip2region_v6.xdb"]), - ok = application:set_env(ip2region, db, [ - {ipv4, "ip2region.xdb"}, - {ipv6, V6File} +xdb_version_mismatch_test() -> + {ok, _} = ip2region_test_util:start_app(), + V4File = filename:join([ + ip2region_test_util:repo_root(), "binding", "erlang", "priv", "ip2region.xdb" ]), - {ok, _} = application:ensure_all_started(ip2region). - -repo_root() -> - TestDir = filename:dirname(?FILE), - ErlangDir = filename:dirname(TestDir), - BindingDir = filename:dirname(ErlangDir), - filename:dirname(BindingDir). + error_logger:tty(false), + try + ?assertEqual( + {error, {xdb_version_mismatch, ipv6, ipv4}}, + ip2region_worker:start([{xdb_file, V4File}, {expected_version, ipv6}]) + ) + after + error_logger:tty(true) + end.