Failing regression tests for #1320

pull/1323/head
Luke Imhoff 6 years ago
parent be37dc342e
commit 51f181db15
  1. 155
      apps/explorer/test/explorer/chain/import/runner/blocks_test.exs
  2. 251
      apps/explorer/test/explorer/chain/import_test.exs

@ -5,34 +5,34 @@ defmodule Explorer.Chain.Import.Runner.BlocksTest do
alias Ecto.Multi
alias Explorer.Chain.Import.Runner.{Blocks, Transaction}
alias Explorer.Chain.{Block, Transaction}
alias Explorer.Chain.{Address, Block, Transaction}
alias Explorer.Repo
describe "run/1" do
setup do
block = insert(:block, consensus: true)
transaction =
:transaction
|> insert()
|> with_block(block)
timestamp = DateTime.utc_now()
options = %{timestamps: %{inserted_at: timestamp, updated_at: timestamp}}
%{consensus_block: block, transaction: transaction}
%{consensus_block: block, options: options}
end
test "derive_transaction_forks replaces hash on conflicting (uncle_hash, index)", %{
consensus_block: %Block{hash: block_hash, miner_hash: miner_hash, number: block_number},
transaction: transaction
consensus_block: %Block{hash: block_hash, miner_hash: miner_hash, number: block_number} = consensus_block,
options: options
} do
transaction =
:transaction
|> insert()
|> with_block(consensus_block)
block_params =
params_for(:block, hash: block_hash, miner_hash: miner_hash, number: block_number, consensus: false)
%Ecto.Changeset{valid?: true, changes: block_changes} = Block.changeset(%Block{}, block_params)
changes_list = [block_changes]
timestamp = DateTime.utc_now()
options = %{timestamps: %{inserted_at: timestamp, updated_at: timestamp}}
assert Repo.aggregate(from(transaction in Transaction, where: is_nil(transaction.block_number)), :count, :hash) ==
0
@ -76,6 +76,139 @@ defmodule Explorer.Chain.Import.Runner.BlocksTest do
assert Repo.one!(from(transaction_fork in Transaction.Fork, select: "ctid")) == ctid,
"Tuple was written even though it is not distinct"
end
test "delete_address_current_token_balances deletes rows with matching block number when consensus is true",
%{consensus_block: %Block{hash: block_hash, miner_hash: miner_hash, number: block_number}, options: options} do
%Address.CurrentTokenBalance{address_hash: address_hash, token_contract_address_hash: token_contract_address_hash} =
insert(:address_current_token_balance, block_number: block_number)
block_params = params_for(:block, hash: block_hash, miner_hash: miner_hash, number: block_number, consensus: true)
%Ecto.Changeset{valid?: true, changes: block_changes} = Block.changeset(%Block{}, block_params)
changes_list = [block_changes]
assert count(Address.CurrentTokenBalance) == 1
assert {:ok,
%{
delete_address_current_token_balances: [
%{address_hash: ^address_hash, token_contract_address_hash: ^token_contract_address_hash}
]
}} =
Multi.new()
|> Blocks.run(changes_list, options)
|> Repo.transaction()
assert count(Address.CurrentTokenBalance) == 0
end
test "delete_address_current_token_balances does not delete rows with matching block number when consensus is false",
%{consensus_block: %Block{hash: block_hash, miner_hash: miner_hash, number: block_number}, options: options} do
%Address.CurrentTokenBalance{} = insert(:address_current_token_balance, block_number: block_number)
block_params =
params_for(:block, hash: block_hash, miner_hash: miner_hash, number: block_number, consensus: false)
%Ecto.Changeset{valid?: true, changes: block_changes} = Block.changeset(%Block{}, block_params)
changes_list = [block_changes]
count = 1
assert count(Address.CurrentTokenBalance) == count
assert {:ok,
%{
delete_address_current_token_balances: []
}} =
Multi.new()
|> Blocks.run(changes_list, options)
|> Repo.transaction()
assert count(Address.CurrentTokenBalance) == count
end
test "derive_address_current_token_balances inserts rows if there is an address_token_balance left for the rows deleted by delete_address_current_token_balances",
%{consensus_block: %Block{hash: block_hash, miner_hash: miner_hash, number: block_number}, options: options} do
%Address.TokenBalance{
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash,
value: previous_value,
block_number: previous_block_number
} = insert(:token_balance, block_number: block_number - 1)
address = Repo.get(Address, address_hash)
%Address.TokenBalance{
address_hash: ^address_hash,
token_contract_address_hash: ^token_contract_address_hash,
value: current_value,
block_number: ^block_number
} =
insert(:token_balance,
address: address,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number
)
refute current_value == previous_value
%Address.CurrentTokenBalance{
address_hash: ^address_hash,
token_contract_address_hash: ^token_contract_address_hash,
block_number: ^block_number,
value: ^current_value
} =
insert(:address_current_token_balance,
address: address,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
value: current_value
)
block_params = params_for(:block, hash: block_hash, miner_hash: miner_hash, number: block_number, consensus: true)
%Ecto.Changeset{valid?: true, changes: block_changes} = Block.changeset(%Block{}, block_params)
changes_list = [block_changes]
assert count(Address.TokenBalance) == 2
assert count(Address.CurrentTokenBalance) == 1
assert {:ok,
%{
delete_address_current_token_balances: [
%{
address_hash: ^address_hash,
token_contract_address_hash: ^token_contract_address_hash
}
],
delete_address_token_balances: [
%{
address_hash: ^address_hash,
token_contract_address_hash: ^token_contract_address_hash,
block_number: ^block_number
}
],
derive_address_current_token_balances: [
%{
address_hash: ^address_hash,
token_contract_address_hash: ^token_contract_address_hash,
block_number: ^previous_block_number
}
]
}} =
Multi.new()
|> Blocks.run(changes_list, options)
|> Repo.transaction()
assert count(Address.TokenBalance) == 1
assert count(Address.CurrentTokenBalance) == 1
assert %Address.CurrentTokenBalance{block_number: ^previous_block_number, value: ^previous_value} =
Repo.get_by(Address.CurrentTokenBalance,
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash
)
end
end
defp count(schema) do

@ -1828,5 +1828,256 @@ defmodule Explorer.Chain.ImportTest do
assert transaction_after.error == nil
assert transaction_after.status == nil
end
test "address_token_balances and address_current_token_balances are deleted during reorgs" do
%Block{number: block_number} = insert(:block, consensus: true)
value_before = Decimal.new(1)
%Address{hash: address_hash} = address = insert(:address)
%Address.TokenBalance{
address_hash: ^address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: ^block_number
} = insert(:token_balance, address: address, block_number: block_number, value: value_before)
%Address.CurrentTokenBalance{
address_hash: ^address_hash,
token_contract_address_hash: ^token_contract_address_hash,
block_number: ^block_number
} =
insert(:address_current_token_balance,
address: address,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
value: value_before
)
miner_hash_after = address_hash()
from_address_hash_after = address_hash()
block_hash_after = block_hash()
assert {:ok, _} =
Import.all(%{
addresses: %{
params: [
%{hash: miner_hash_after},
%{hash: from_address_hash_after}
]
},
blocks: %{
params: [
%{
consensus: true,
difficulty: 1,
gas_limit: 1,
gas_used: 1,
hash: block_hash_after,
miner_hash: miner_hash_after,
nonce: 1,
number: block_number,
parent_hash: block_hash(),
size: 1,
timestamp: Timex.parse!("2019-01-01T02:00:00Z", "{ISO:Extended:Z}"),
total_difficulty: 1
}
]
}
})
assert is_nil(
Repo.get_by(Address.CurrentTokenBalance,
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash
)
)
assert is_nil(
Repo.get_by(Address.TokenBalance,
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number
)
)
end
test "address_current_token_balances is derived during reorgs" do
%Block{number: block_number} = insert(:block, consensus: true)
previous_block_number = block_number - 1
%Address.TokenBalance{
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash,
value: previous_value,
block_number: previous_block_number
} = insert(:token_balance, block_number: previous_block_number)
address = Repo.get(Address, address_hash)
%Address.TokenBalance{
address_hash: ^address_hash,
token_contract_address_hash: token_contract_address_hash,
value: current_value,
block_number: ^block_number
} =
insert(:token_balance,
address: address,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number
)
refute current_value == previous_value
%Address.CurrentTokenBalance{
address_hash: ^address_hash,
token_contract_address_hash: ^token_contract_address_hash,
block_number: ^block_number
} =
insert(:address_current_token_balance,
address: address,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
value: current_value
)
miner_hash_after = address_hash()
from_address_hash_after = address_hash()
block_hash_after = block_hash()
assert {:ok, _} =
Import.all(%{
addresses: %{
params: [
%{hash: miner_hash_after},
%{hash: from_address_hash_after}
]
},
blocks: %{
params: [
%{
consensus: true,
difficulty: 1,
gas_limit: 1,
gas_used: 1,
hash: block_hash_after,
miner_hash: miner_hash_after,
nonce: 1,
number: block_number,
parent_hash: block_hash(),
size: 1,
timestamp: Timex.parse!("2019-01-01T02:00:00Z", "{ISO:Extended:Z}"),
total_difficulty: 1
}
]
}
})
assert %Address.CurrentTokenBalance{block_number: ^previous_block_number, value: ^previous_value} =
Repo.get_by(Address.CurrentTokenBalance,
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash
)
assert is_nil(
Repo.get_by(Address.TokenBalance,
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number
)
)
end
test "address_token_balances and address_current_token_balances can be replaced during reorgs" do
%Block{number: block_number} = insert(:block, consensus: true)
value_before = Decimal.new(1)
%Address{hash: address_hash} = address = insert(:address)
%Address.TokenBalance{
address_hash: ^address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: ^block_number
} = insert(:token_balance, address: address, block_number: block_number, value: value_before)
%Address.CurrentTokenBalance{
address_hash: ^address_hash,
token_contract_address_hash: ^token_contract_address_hash,
block_number: ^block_number
} =
insert(:address_current_token_balance,
address: address,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
value: value_before
)
miner_hash_after = address_hash()
from_address_hash_after = address_hash()
block_hash_after = block_hash()
value_after = Decimal.add(value_before, 1)
assert {:ok, _} =
Import.all(%{
addresses: %{
params: [
%{hash: address_hash},
%{hash: token_contract_address_hash},
%{hash: miner_hash_after},
%{hash: from_address_hash_after}
]
},
address_token_balances: %{
params: [
%{
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
value: value_after
}
]
},
address_current_token_balances: %{
params: [
%{
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number,
value: value_after
}
]
},
blocks: %{
params: [
%{
consensus: true,
difficulty: 1,
gas_limit: 1,
gas_used: 1,
hash: block_hash_after,
miner_hash: miner_hash_after,
nonce: 1,
number: block_number,
parent_hash: block_hash(),
size: 1,
timestamp: Timex.parse!("2019-01-01T02:00:00Z", "{ISO:Extended:Z}"),
total_difficulty: 1
}
]
}
})
assert %Address.CurrentTokenBalance{value: ^value_after} =
Repo.get_by(Address.CurrentTokenBalance,
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash
)
assert %Address.TokenBalance{value: ^value_after} =
Repo.get_by(Address.TokenBalance,
address_hash: address_hash,
token_contract_address_hash: token_contract_address_hash,
block_number: block_number
)
end
end
end

Loading…
Cancel
Save