Skip to content
This repository has been archived by the owner on Aug 18, 2020. It is now read-only.

[CBR-371] unit tests for listing addresses #3563

Merged
merged 5 commits into from
Sep 17, 2018
Merged

Conversation

kderme
Copy link
Member

@kderme kderme commented Sep 9, 2018

Description

This PR adds tests for listing addresses:

  • the results are always deterministic (in the sense that doing the same request 2 times yields the same response)
  • paginating the results, yields no duplicate results.
  • paginating the results may bring them in a different order (e.g. requesting 10 + 10 results in two pages will bring the same results but in different order than if we requested 20 in one page).
  • The last point does not apply if there is a single account. In that case results are always in the same order.

UPDATE: a very small bug affected pagination when there are multiple accounts (see the diff in wallet-new/src/Cardano/Wallet/WalletLayer/Kernel/Addresses.hs). Now order is consistent always.

Linked issue

https://iohk.myjetbrains.com/youtrack/issue/CBR-371

Type of change

  • 🐞 Bug fix (non-breaking change which fixes an issue)
  • 🛠 New feature (non-breaking change which adds functionality)
  • ⚠️ Breaking change (fix or feature that would cause existing functionality to change)
  • 🏭 Refactoring that does not change existing functionality but does improve things like code readability, structure etc
  • 🔨 New or improved tests for existing code
  • ⛑ git-flow chore (backport, hotfix, etc)

Developer checklist

  • I have read the style guide document, and my code follows the code style of this project.
  • If my code deals with exceptions, it follows the guidelines.
  • I have updated any documentation accordingly, if needed. Documentation changes can be reflected in opening a PR on cardanodocs.com, amending the inline Haddock comments, any relevant README file or one of the document listed in the docs directory.
  • CHANGELOG entry has been added and is linked to the correct PR on GitHub.

Testing checklist

  • I have added tests to cover my changes.
  • All new and existing tests passed.

QA Steps

Screenshots (if available)

@kderme kderme added the wip label Sep 9, 2018
@kderme kderme removed the wip label Sep 10, 2018
@kderme kderme changed the title [WIP] [CBR-371] unit tests for listing addresses [CBR-371] unit tests for listing addresses Sep 10, 2018
Copy link
Contributor

@adinapoli-iohk adinapoli-iohk left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job @kderme ! We are getting there, but I think we can do slightly better in the code design space. I have jotted down some ideas. Let me know what you think!

db <- Kernel.getWalletSnapshot pw
let Right accs = Accounts.getAccounts (V1.walId v1Wallet) db
let accounts = IxSet.toList accs
length accounts `shouldBe` (acn + 1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would recommend flipping the logic and doing something like:

prepareAddressFixture acn adn = 
    -- We recompute the values to account for the fact that creating a new wallet
    -- @always@ come with a fresh account, and this account always have a fresh address
    -- associated with it.
    let requestedAccounts = max 0 (acn - 1)
    let requestedAddresses = max 0 (adn - 1)

Then, you can use those two let bindings all over the place without having to worry about +1/-1 arithmetic, both in the fixtures and in the tests. Furthermore, you segregate the comment on why we do this exactly in one point in the code, without this assumption being scattered all over the place.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand what are the semantics of requestedAddresses. Some accounts will have requestedAddresses addresses, while the first account will have requestedAddresses+1. Also requestedAccounts should never be 0, as one account is created by default.

return $ M.fromList res

expectedNumber :: Int -> Int -> Int
expectedNumber acc adr = (acc + 1)*(adr + 1) - acc
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you bake the logic inside the fixture, you might be able to remove this.

Right wr -> do
-- this takes into account that there is an initial account
-- and each account has an initial address (but not the initial
-- account thus the -1)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, unfortunately if you create multiple accounts for the same wallet those won't come with an extra associated address. But ideally, if you can bake this inside the fixture creation, test logic should hopefully simplify 😉

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should delete this comment.

let pp = PaginationParams (Page 1) (PerPage 40)
let pp1 = PaginationParams (Page 1) (PerPage (quot expectedTotal 3 + 1))
let pp2 = PaginationParams (Page 2) (PerPage (quot expectedTotal 3 + 1))
let pp3 = PaginationParams (Page 3) (PerPage (quot expectedTotal 3 + 1))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a bit dense for the reader to try to figure out why you do the quot expectedTotal dance, but hopefully we can simplify this one.

res `shouldBe` res'
res1 `shouldBe` res1'
res2 `shouldBe` res2'
res3 `shouldBe` res3'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea: considering is very error prone to go for this style of foo, foo', bar, bar', why don't you write something like this?

                        res <- runExceptT $ runHandler' $ do
                            r1 <- Handlers.listAddresses layer (RequestParams pp)
                            r2 <- Handlers.listAddresses layer (RequestParams pp)
                            pure (r1 === r2)
                        res1 <- runExceptT $ runHandler' $ do
                            r1 <- Handlers.listAddresses layer (RequestParams pp1)
                            r2 <- Handlers.listAddresses layer (RequestParams pp1)
                            pure (r1 === r2)
                       assert $ conjoin [res, res1]

Even better, I think you can simplify this even further by noticing how this is just iterating over [pp,pp1,pp2,pp3] but executing mechanical actions, so you can write something which runs a forM, calls internally replicateM 2 , yields a Property and conjoin everything at the end.

S.fromList con `shouldBe` S.fromList (wrData wr)
(addrRoot . V1.unV1 . V1.addrId <$> con)
`shouldBe` (addrRoot . V1.unV1 . V1.addrId <$> wrData wr)
_ -> fail ("Got " ++ show res)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a minor thing, but these tests feels very imperative rather than declarative. I don't know what we can do about it, but I suspect we might come up with some combinators which factor away duplication and mechanical reshuffling of the data and leave the logic of the tests exposes. I guess what we aim is something like:

myTest = do
    -- Initialisation
    -- Execution
    -- Checking of properties

Which is exactly what your tests are also doing, but each of these steps takes a lot of lines of code and is hard to track down the spirit of the test 😉

@adinapoli-iohk
Copy link
Contributor

We discussed this with @kderme , and we agreed he will open a separate ticket for the cleanup as requested by my original review.

@adinapoli-iohk adinapoli-iohk merged commit 76bea25 into develop Sep 17, 2018
@adinapoli-iohk adinapoli-iohk deleted the kderme/CBR-371 branch September 17, 2018 11:28
@kderme
Copy link
Member Author

kderme commented Sep 17, 2018

cleanup ticket at https://iohk.myjetbrains.com/youtrack/issue/CBR-435

KtorZ pushed a commit that referenced this pull request Nov 9, 2018
[CBR-371] unit tests for listing addresses
KtorZ pushed a commit to input-output-hk/cardano-wallet-legacy that referenced this pull request Nov 9, 2018
…hk/kderme/CBR-371

[CBR-371] unit tests for listing addresses
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants