-
Notifications
You must be signed in to change notification settings - Fork 458
feat: remote tests mocking #701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: remote tests mocking #701
Conversation
…ion called in a transaction
func callTransaction(_ transaction: CodableTransaction) async throws -> Data { | ||
onCallTransaction?(transaction) ?? Data() | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we need any other function to mock we just add it here.
switch function.name { | ||
case "investorCount": | ||
return ABIEncoder.encode(types: [.uint(bits: 256)], values: [expectedNumberOfInvestors] as [AnyObject])! | ||
// case "investors": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Calling try await securityToken.investors()
crashes.
The ABI and Swift implementations do not match. In ABI it expects uint256 argument as I recall but in Swift we try to call just investors
function without arguments.
TODO: must fix the implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Todo or Fixme? I mean do you planning to fix it within this PR or is it a task for some better times?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not with this PR. I'll push a separate one as it's unrelated issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Removed commented code.
Fixing will be done in another PR.
/// Given the transaction data searches for a match in ``ContractProtocol/methods``. | ||
/// - Parameter data: encoded function call used in transaction data field. Must be at least 4 bytes long. | ||
/// - Returns: function decoded from the ABI of this contract or `nil` if nothing was found. | ||
func getFunctionCalled(_ data: Data) -> ABI.Element.Function? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My dream for 4.0.0 is to create a set of Ethereum only data types that will be accounts all that special cases.
Must be at least 4 bytes long.
Because while we're using some advantages of swift strong typed system in 3.0.0 we're still missing a lot of them, treating those Ethereum rules in a python way, by leaving notes to our future selves.
Nothing to say about rewriting ABI module to generics as well.
public func getFunctionCalled(_ data: Data) -> ABI.Element.Function? { | ||
guard data.count >= 4 else { return nil } | ||
return methods[data[0..<4].toHexString().addHexPrefix()]?.first | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, I see your dirty hack here. This is somewhat that I'd like to be implemented as a protocol. But again this is dream not even about current century.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not that dirty I'd say.
We have an array of bytes, we get the first 4 of them and then look them up in the dictionary.
It's pretty straightforward.
override func setUp() async throws { | ||
web3 = await Web3.InfuraGoerliWeb3(accessToken: Constants.infuraToken) | ||
ethMock = Web3EthMock(provider: web3.provider) | ||
web3.ethInstance = ethMock | ||
st20token = ST20.init(web3: web3, provider: web3.provider, address: .contractDeploymentAddress()) | ||
securityToken = SecurityToken.init(web3: web3, provider: web3.provider, address: .contractDeploymentAddress()) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct me if I'm wrong: Is the all mocking happening just here, or I missing something?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the setup for mocking. The thing that is identical for all tests.
But each individual test mocks callTransaction
function and is able to intercept the incoming requests and decide what to return in each separate test.
switch function.name { | ||
case "investorCount": | ||
return ABIEncoder.encode(types: [.uint(bits: 256)], values: [expectedNumberOfInvestors] as [AnyObject])! | ||
// case "investors": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Todo or Fixme? I mean do you planning to fix it within this PR or is it a task for some better times?
|
||
let investorsCount = try await securityToken.investorCount() | ||
XCTAssertEqual(investorsCount, expectedNumberOfInvestors) | ||
// XCTAssertEqual(investors, expectedInvestors) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comments should be dropped though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's definitely not coming with this PR, just wanted to highlight that we have issues with either ABI or the implementation.
One of the conclusions that I have is that each and every ABI like Web3.Utils.st20ABI
and the rest must be precisely the version of ABI that matches the original standard without any deviation.
Since we allow developers to reference these ABIs from our project it's our responsibility to:
- validate the ABI (it must match the standard);
- give the link to the place where we got this ABI from;
- recommend developers to use their own ABIs if that's possible as they will have more control over that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yaroslavyaroslav @janndriessen Here is the fix for these commented out lines - #704
The branch with the fix is not based on the one in the current PR so I'll be able to update tests only when the fix is merged into develop
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only one additional comment. Indeed the work load for mocking looks manageable. Thanks for introducing/working on this.
@@ -60,7 +57,7 @@ public class Web3 { | |||
// FIXME: Rewrite this to CodableTransaction | |||
public class Personal { | |||
var provider: Web3Provider | |||
// weak var web3: web3? | |||
// FIXME: web3 must be weak |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this will be fixed in another PR?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. Just made it more obvious that it needs fixing instead of a commented line of code that tells nothing.
I'll actually update the part after FIXME. Ideally we should remove web3
reference from here completely.
@yaroslavyaroslav @janndriessen Thanks for taking the time to look at this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🌟 ✅
The reason for this PR: tests in #685 fail due to the Kovan testnet being deprecated and it requires a redeploy of all smart contracts we use for testing on actually running remote networks.
What is introduced in this PR?
CodableTransaction.data
without the need for developers to extract the method ID each time;string
andbyte
. More tests will be added in upcoming PRs.I've tried to use mock or make it easy to redeploy smart contracts on a new testnet.
Mocking libraries are not working in Swift as they do in other languages like e.g. Java. Swift has limitations on reflection and we cannot easily mock function calls and especially when these functions are in the
extension
block. I've tried using https://github.com/birdrides/mockingbird/ but in the end it failed in a sense that it will not allow to mock the parts we need due to how our code is written + Swift reflection limitations.Another solution was to write "helper" functions that will deploy smart contracts on a selected chain. It has the following downsides:
The con of this update is that we have to implement mocks ourselves. It doesn't look difficult for now.