Skip to content

Commit e546c95

Browse files
authored
chore: Stabilize various flaky tests (blockscout#14149)
1 parent 9eead37 commit e546c95

24 files changed

Lines changed: 424 additions & 95 deletions

apps/block_scout_web/test/block_scout_web/channels/exchange_rate_channel_test.exs

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ defmodule BlockScoutWeb.ExchangeRateChannelTest do
66
alias BlockScoutWeb.Notifier
77
alias Explorer.Market
88
alias Explorer.Market.Fetcher.Coin
9-
alias Explorer.Market.{MarketHistory, Token}
9+
alias Explorer.Market.{MarketHistory, MarketHistoryCache, Token}
1010
alias Explorer.Market.Source.TestSource
1111

1212
setup :verify_on_exit!
@@ -46,8 +46,8 @@ defmodule BlockScoutWeb.ExchangeRateChannelTest do
4646
describe "new_rate" do
4747
test "subscribed user is notified", %{token: token} do
4848
Coin.handle_info({nil, {{:ok, token}, false}}, %{})
49-
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Market.MarketHistoryCache.cache_name()})
50-
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Market.MarketHistoryCache.cache_name()})
49+
ConCache.delete(MarketHistoryCache.cache_name(), MarketHistoryCache.updated_at_key())
50+
ConCache.delete(MarketHistoryCache.cache_name(), MarketHistoryCache.data_key())
5151

5252
topic = "exchange_rate_old:new_rate"
5353
@endpoint.subscribe(topic)
@@ -73,8 +73,8 @@ defmodule BlockScoutWeb.ExchangeRateChannelTest do
7373
end)
7474

7575
Coin.handle_info({nil, {{:ok, token}, false}}, %{})
76-
Supervisor.terminate_child(Explorer.Supervisor, {ConCache, Explorer.Market.MarketHistoryCache.cache_name()})
77-
Supervisor.restart_child(Explorer.Supervisor, {ConCache, Explorer.Market.MarketHistoryCache.cache_name()})
76+
ConCache.delete(MarketHistoryCache.cache_name(), MarketHistoryCache.updated_at_key())
77+
ConCache.delete(MarketHistoryCache.cache_name(), MarketHistoryCache.data_key())
7878

7979
today = Date.utc_today()
8080

@@ -90,7 +90,10 @@ defmodule BlockScoutWeb.ExchangeRateChannelTest do
9090

9191
MarketHistory.bulk_insert(records)
9292

93-
Market.fetch_recent_history()
93+
ConCache.delete(MarketHistoryCache.cache_name(), MarketHistoryCache.updated_at_key())
94+
ConCache.delete(MarketHistoryCache.cache_name(), MarketHistoryCache.data_key())
95+
96+
assert Enum.map(Market.fetch_recent_history(), &Map.take(&1, [:date, :closing_price])) == records
9497

9598
topic = "exchange_rate_old:new_rate"
9699
@endpoint.subscribe(topic)

apps/block_scout_web/test/block_scout_web/channels/v2/block_channel_test.exs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ defmodule BlockScoutWeb.V2.BlockChannelTest do
22
use BlockScoutWeb.ChannelCase
33

44
alias BlockScoutWeb.Notifier
5+
alias Explorer.Chain.Address
56
alias Explorer.Chain.Cache.Counters.AverageBlockTime
67
alias Plug.Conn
78

@@ -90,7 +91,7 @@ defmodule BlockScoutWeb.V2.BlockChannelTest do
9091
200,
9192
Jason.encode!(%{
9293
"names" => %{
93-
to_string(miner.hash) => "miner.eth"
94+
Address.checksum(miner.hash) => "miner.eth"
9495
}
9596
})
9697
)
@@ -102,7 +103,7 @@ defmodule BlockScoutWeb.V2.BlockChannelTest do
102103
200,
103104
Jason.encode!(%{
104105
"addresses" => %{
105-
to_string(miner.hash) => %{
106+
Address.checksum(miner.hash) => %{
106107
"tags" => []
107108
}
108109
}

apps/block_scout_web/test/block_scout_web/controllers/account/api/v2/authenticate_controller_test.exs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,19 @@ defmodule BlockScoutWeb.Account.API.V2.AuthenticateControllerTest do
33

44
alias Explorer.Account.Identity
55
alias Explorer.Chain.Address
6+
alias Explorer.Helper
7+
alias Explorer.ThirdPartyIntegrations.Auth0.Internal
68
alias Explorer.ThirdPartyIntegrations.Dynamic
79
alias Explorer.ThirdPartyIntegrations.Dynamic.Strategy
810

911
import Mox
1012

13+
setup do
14+
Redix.command(:redix, ["DEL", Helper.redis_key(Internal.redis_key())])
15+
16+
:ok
17+
end
18+
1119
describe "POST api/account/v2/send_otp" do
1220
test "send OTP successfully", %{conn: conn} do
1321
Tesla.Test.expect_tesla_call(

apps/block_scout_web/test/block_scout_web/controllers/address_token_transfer_controller_test.exs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,11 +151,12 @@ defmodule BlockScoutWeb.AddressTokenTransferControllerTest do
151151
test "returns next_page_path when there are more items", %{conn: conn} do
152152
address = insert(:address)
153153
token = insert(:token)
154+
start_block_number = 2_000_000 + System.unique_integer([:positive])
154155

155156
page_last_transfer =
156157
1..50
157158
|> Enum.map(fn index ->
158-
block = insert(:block, number: 1000 - index)
159+
block = insert(:block, number: start_block_number - index)
159160

160161
transaction =
161162
:transaction
@@ -174,7 +175,7 @@ defmodule BlockScoutWeb.AddressTokenTransferControllerTest do
174175
|> List.last()
175176

176177
Enum.each(51..60, fn index ->
177-
block = insert(:block, number: 1000 - index)
178+
block = insert(:block, number: start_block_number - index)
178179

179180
transaction =
180181
:transaction

apps/block_scout_web/test/block_scout_web/controllers/api/v2/address_controller_test.exs

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ defmodule BlockScoutWeb.API.V2.AddressControllerTest do
2828
alias Indexer.Fetcher.OnDemand.ContractCode, as: ContractCodeOnDemand
2929
alias Plug.Conn
3030

31+
import Ecto.Query, only: [from: 2]
3132
import Explorer.Chain, only: [hash_to_lower_case_string: 1]
3233
import Mox
3334

@@ -974,7 +975,7 @@ defmodule BlockScoutWeb.API.V2.AddressControllerTest do
974975

975976
transactions =
976977
(transactions_from ++ transactions_to)
977-
|> Enum.sort(&(Decimal.compare(Wei.to(&1.value, :wei), Wei.to(&2.value, :wei)) in [:eq, :lt]))
978+
|> sort_transactions_by_value(:asc)
978979

979980
request = get(conn, "/api/v2/addresses/#{address.hash}/transactions", %{"sort" => "value", "order" => "asc"})
980981
assert response = json_response(request, 200)
@@ -1008,7 +1009,7 @@ defmodule BlockScoutWeb.API.V2.AddressControllerTest do
10081009

10091010
transactions =
10101011
(transactions_from ++ transactions_to)
1011-
|> Enum.sort(&(Decimal.compare(Wei.to(&1.value, :wei), Wei.to(&2.value, :wei)) in [:eq, :gt]))
1012+
|> sort_transactions_by_value(:desc)
10121013

10131014
request = get(conn, "/api/v2/addresses/#{address.hash}/transactions", %{"sort" => "value", "order" => "desc"})
10141015
assert response = json_response(request, 200)
@@ -5702,8 +5703,29 @@ defmodule BlockScoutWeb.API.V2.AddressControllerTest do
57025703
assert to_string(cb.value.value) == json["value"]
57035704
assert cb.block_number == json["block_number"]
57045705

5705-
assert Jason.encode!(Repo.get_by(Block, number: cb.block_number).timestamp) =~
5706-
String.replace(json["block_timestamp"], "Z", "")
5706+
# The API uses linear interpolation over the fetched set (page_size + 1 items),
5707+
# so the returned timestamp may be off by up to 1 second from the actual block
5708+
# timestamp. Allow ±1 second tolerance to account for this artifact.
5709+
expected_timestamps =
5710+
Repo.all(
5711+
from(block in Block,
5712+
where: block.number == ^cb.block_number,
5713+
select: block.timestamp
5714+
)
5715+
)
5716+
|> Enum.flat_map(fn ts ->
5717+
truncated = DateTime.truncate(ts, :second)
5718+
5719+
[
5720+
DateTime.add(truncated, -1, :second),
5721+
truncated,
5722+
DateTime.add(truncated, 1, :second)
5723+
]
5724+
end)
5725+
|> Enum.uniq()
5726+
5727+
{:ok, response_timestamp, 0} = DateTime.from_iso8601(json["block_timestamp"])
5728+
assert DateTime.truncate(response_timestamp, :second) in expected_timestamps
57075729
end
57085730

57095731
defp compare_item(%Token{} = token, json) do
@@ -5877,6 +5899,35 @@ defmodule BlockScoutWeb.API.V2.AddressControllerTest do
58775899
defp value("ERC-721", _), do: 1
58785900
defp value(_, nft), do: nft.current_token_balance.value
58795901

5902+
defp sort_transactions_by_value(transactions, order) do
5903+
Enum.sort(transactions, fn a, b ->
5904+
case Decimal.compare(Wei.to(a.value, :wei), Wei.to(b.value, :wei)) do
5905+
:lt -> order == :asc
5906+
:gt -> order == :desc
5907+
:eq -> compare_transactions_default_order(a, b)
5908+
end
5909+
end)
5910+
end
5911+
5912+
defp compare_transactions_default_order(a, b) do
5913+
case {
5914+
compare_values(a.block_number, b.block_number),
5915+
compare_values(a.index, b.index),
5916+
DateTime.compare(a.inserted_at, b.inserted_at),
5917+
compare_values(to_string(a.hash), to_string(b.hash))
5918+
} do
5919+
{:lt, _, _, _} -> false
5920+
{:eq, :lt, _, _} -> false
5921+
{:eq, :eq, :lt, _} -> false
5922+
{:eq, :eq, :eq, :gt} -> false
5923+
_ -> true
5924+
end
5925+
end
5926+
5927+
defp compare_values(a, b) when a < b, do: :lt
5928+
defp compare_values(a, b) when a > b, do: :gt
5929+
defp compare_values(_, _), do: :eq
5930+
58805931
defp check_paginated_response(first_page_resp, second_page_resp, list) do
58815932
assert Enum.count(first_page_resp["items"]) == 50
58825933
assert first_page_resp["next_page_params"] != nil

apps/block_scout_web/test/support/feature_case.ex

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ defmodule BlockScoutWeb.FeatureCase do
3131
Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Transactions.child_id())
3232
Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Accounts.child_id())
3333
Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Accounts.child_id())
34+
Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id())
35+
Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Blocks.child_id())
36+
Supervisor.terminate_child(Explorer.Supervisor, Explorer.Chain.Cache.Uncles.child_id())
37+
Supervisor.restart_child(Explorer.Supervisor, Explorer.Chain.Cache.Uncles.child_id())
3438

3539
metadata = Phoenix.Ecto.SQL.Sandbox.metadata_for(Explorer.Repo, self())
3640
{:ok, session} = Wallaby.start_session(metadata: metadata)

apps/explorer/lib/explorer/etherscan/logs.ex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ defmodule Explorer.Etherscan.Logs do
9999
block_timestamp: transaction.block_timestamp,
100100
block_consensus: transaction.block_consensus
101101
},
102+
order_by: [asc: transaction.block_number, asc: log.index],
102103
limit: 1000
103104
)
104105

@@ -123,6 +124,7 @@ defmodule Explorer.Etherscan.Logs do
123124
block_timestamp: block.timestamp,
124125
block_consensus: block.consensus
125126
},
127+
order_by: [asc: block.number, asc: log.index],
126128
limit: 1000
127129
)
128130

apps/explorer/lib/explorer/third_party_integrations/auth0/legacy.ex

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,11 +101,12 @@ defmodule Explorer.ThirdPartyIntegrations.Auth0.Legacy do
101101
@spec find_or_create_web3_user(String.t(), String.t()) :: {:ok, map()} | :error | {:error, String.t()}
102102
def find_or_create_web3_user(address, signature) do
103103
case Internal.find_users_by_web3_address(address) do
104-
{:ok, [%{"user_metadata" => %{"web3_address_hash" => ^address}} = user]} ->
105-
{:ok, user}
106-
107-
{:ok, [%{"user_id" => user_id}]} ->
108-
update_user_with_web3_address(user_id, address)
104+
{:ok, [user]} ->
105+
if same_web3_address?(user, address) do
106+
{:ok, user}
107+
else
108+
update_user_with_web3_address(user["user_id"], address)
109+
end
109110

110111
{:ok, []} ->
111112
Internal.create_web3_user(address, signature, %{web3_address_hash: address})
@@ -176,6 +177,13 @@ defmodule Explorer.ThirdPartyIntegrations.Auth0.Legacy do
176177

177178
defp maybe_verify_email(_), do: :ok
178179

180+
defp same_web3_address?(%{"user_metadata" => %{"web3_address_hash" => stored_address}}, address)
181+
when is_binary(stored_address) do
182+
String.downcase(stored_address) == String.downcase(address)
183+
end
184+
185+
defp same_web3_address?(_, _), do: false
186+
179187
defp merge_email_users([primary_user | _] = users, identity_id_to_link, provider_for_linking) do
180188
identity_map = get_identity_map(users)
181189

apps/explorer/lib/explorer/token/metadata_retriever.ex

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -245,13 +245,21 @@ defmodule Explorer.Token.MetadataRetriever do
245245
Map.put(
246246
metadata,
247247
:skip_metadata,
248-
Enum.all?(raw_metadata, fn {_key, value} -> EthereumJSONRPC.contract_failure?(value) end)
248+
Enum.all?(raw_metadata, fn {_key, value} -> contract_failure?(value) end)
249249
)
250250
else
251251
metadata
252252
end
253253
end
254254

255+
defp contract_failure?({:error, %{message: message}}) when is_binary(message),
256+
do: String.match?(message, ~r/execution.*revert/)
257+
258+
defp contract_failure?({:error, %{data: data}}) when is_binary(data),
259+
do: String.match?(data, ~r/execution.*revert/)
260+
261+
defp contract_failure?(error), do: EthereumJSONRPC.contract_failure?(error)
262+
255263
defp try_to_fetch_erc_1155_name(base_metadata, contract_address_hash, token_type) do
256264
if token_type == "ERC-1155" && !Map.has_key?(base_metadata, :name) do
257265
erc_1155_name_uri =

apps/explorer/test/explorer/chain/import/runner/address/current_token_balances_test.exs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ defmodule Explorer.Chain.Import.Runner.Address.CurrentTokenBalancesTest do
307307
assert current_token_balance.value == Decimal.new(200)
308308
end
309309

310-
test "ignores when the new value_fetched_at not set", %{
310+
test "updates when the new block number is greater even if value_fetched_at is not set", %{
311311
address: %Address{hash: address_hash} = address,
312312
token: %Token{contract_address_hash: token_contract_address_hash},
313313
options: options
@@ -323,7 +323,7 @@ defmodule Explorer.Chain.Import.Runner.Address.CurrentTokenBalancesTest do
323323

324324
update_holder_count!(token_contract_address_hash, 1)
325325

326-
assert {:ok, %{address_current_token_balances: [], address_current_token_balances_update_token_holder_counts: []}} =
326+
assert {:ok, %{address_current_token_balances_update_token_holder_counts: []}} =
327327
run_changes(
328328
%{
329329
address_hash: address_hash,
@@ -336,8 +336,8 @@ defmodule Explorer.Chain.Import.Runner.Address.CurrentTokenBalancesTest do
336336

337337
current_token_balance = Repo.get_by(CurrentTokenBalance, address_hash: address_hash)
338338

339-
assert current_token_balance.block_number == 1
340-
assert current_token_balance.value == Decimal.new(200)
339+
assert current_token_balance.block_number == 2
340+
assert current_token_balance.value == Decimal.new(100)
341341
end
342342

343343
test "ignores when the new block number is lesser", %{

0 commit comments

Comments
 (0)