Skip to content
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

Add tests for the ordinary index #362

Open
wants to merge 5 commits into
base: main
Choose a base branch
from

Conversation

jeltsch
Copy link
Collaborator

@jeltsch jeltsch commented Aug 30, 2024

This adds tests for the ordinary index.

Currently, the property prop_searchForUnmentionedKeyBeyondRangeWorks tends to discard too many test cases. I will address this and then drop the draft status of this pull request.

@jeltsch jeltsch added the enhancement New feature or request label Aug 30, 2024
@jeltsch jeltsch self-assigned this Aug 30, 2024
@jeltsch jeltsch marked this pull request as ready for review August 31, 2024 23:51
Copy link
Collaborator

@mheinzel mheinzel left a comment

Choose a reason for hiding this comment

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

Looks good, a few suggestions.

Comment on lines +63 to +64
fromIndexOrdinary :: IndexOrdinary -> Vector SerialisedKey
fromIndexOrdinary (IndexOrdinary lastKeys) = lastKeys
Copy link
Collaborator

Choose a reason for hiding this comment

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

Since the module is supposed to be imported qualified, mentioning the name again is redundant (IndexOrdinary.fromIndexOrdinary). Maybe focussing on the result, e.g. toLastKeys or lastKeysPerPage?


{-# OPTIONS_GHC -Wno-orphans #-}

{- HLINT ignore "Avoid restricted alias" -}
Copy link
Collaborator

Choose a reason for hiding this comment

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

I think these hints are all custom ones we specifically added to our hlint config, and I think it makes sense to use qualified imports consistently. I see that we already have a few similar HLINT ignore exceptions in src, but I don't think it's a good idea. If we're not consistent about it, we might as well get rid of the hlint rules, but I'd rather follow them.

Comment on lines +303 to +306
key < selectionHead .&&.
all (< key) prefix .&&.
all (== selectionHead) (tail selection) .&&.
all (> selectionHead) suffix
Copy link
Collaborator

Choose a reason for hiding this comment

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

If this test fails, it's hard to find out why. QC.=== is nicer, but unfortunately there's nothing similar for < etc. (Might be worth adding locally?). Then some QC.conjoin to combine these properties and maybe a QC.counterexample to make it clear which part failed (selectionHead/prefix/selection/suffix).

We can defer adding these niceties until someone has to debug a failure, but it's nice to do it right away. At least a counterexample (show (prefix, selection, suffix)) around everything, so we see what search returned.

Comment on lines +322 to +324
= not (null lesserLastKeys) ==> all (< selectionHead) prefix .&&.
all (== selectionHead) (tail selection) .&&.
all (> selectionHead) suffix
Copy link
Collaborator

Choose a reason for hiding this comment

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

Ah, at first I didn't see how that ensure that the key is unmentioned and beyond range, but we construct new index to have that. Makes sense.

But why do we still check the same properties? Couldn't we just say that prefix === lesserLastKeys and the rest is empty?

input :: ShortByteString
input = potentialSerialisedIndex
testedTypeAndVersionBlock
(lastKeysBlocks lastKeys ++ [statedSizeBlock, partialKeyBlock])
Copy link
Collaborator

Choose a reason for hiding this comment

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

Yes, nice. Maybe one more test with a completely random key block would make sense, where we don't care about Left/Right, just that the result is QC.total. But this here should already cover the case of a key length going out of range. 👍

Comment on lines +435 to +451
instance Arbitrary NumEntries where

arbitrary = NumEntries <$> (getNonNegative <$> arbitrary)
`suchThat`
(toInteger >>> (< 2 ^ (64 :: Int)))

-- This shrinker relies on 'Int' values not becoming greater by shrinking.
shrink = shrinkMap (NumEntries . getNonNegative)
(\ (NumEntries entryCount) -> NonNegative entryCount)

instance Arbitrary SerialisedKey where

arbitrary = SerialisedKey' <$>
arbitrary `suchThat` (Primitive.length >>> (< 0x10000))

-- This shrinker relies on lists not becoming longer by shrinking.
shrink = shrinkMap SerialisedKey' (\ (SerialisedKey' bytes) -> bytes)
Copy link
Collaborator

Choose a reason for hiding this comment

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

We already have these instances in src-extras/../Generators.hs. The distribution for the second one might be a bit different, but I don't think it's a problem.

SearchableIndex (indexFromLastKeys lastKeys') |
lastKeys' <- shrink (toList lastKeysVec),
not (null lastKeys'),
and (zipWith (<=) lastKeys' (List.tail lastKeys'))
Copy link
Collaborator

Choose a reason for hiding this comment

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

neat

Comment on lines +502 to +525
instance Arbitrary Append where

arbitrary = oneof $
[
AppendSinglePage <$> arbitrary <*> arbitrary,
AppendMultiPage <$> arbitrary <*> (getSmall <$> arbitrary)
]

shrink (AppendSinglePage firstKey lastKey)
= [AppendSinglePage firstKey' lastKey | firstKey' <- shrink firstKey] ++
[AppendSinglePage firstKey lastKey' | lastKey' <- shrink lastKey]
shrink (AppendMultiPage key overflowPageCount)
= [AppendSinglePage key key]
++
[
AppendMultiPage key' overflowPageCount |
key' <- shrink key
]
++
[
AppendMultiPage key overflowPageCount' |
overflowPageCount' <- shrinkMap getSmall Small $
overflowPageCount
]
Copy link
Collaborator

Choose a reason for hiding this comment

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

Another way of doing this (which also the compact index tests use) would be to use the existing generators for LogicalPageSummaries, which has a function toAppends :: _ -> [Append].

@mheinzel
Copy link
Collaborator

Also, would be nice to see a rebase making the tests pass in CI. They pass for me locally when I rebase, but would be nice to see it here as well.

The new implementation doesn’t lead to QuickCheck discarding too many
test cases. The downside of it is that the indexes this property uses
for search are only half the size on average.
@jeltsch
Copy link
Collaborator Author

jeltsch commented Sep 24, 2024

Also, would be nice to see a rebase making the tests pass in CI. They pass for me locally when I rebase, but would be nice to see it here as well.

Sure thing, and, since #363 is finally merged, I performed the rebasing. Let’s see if the builds succeed now.

@jeltsch
Copy link
Collaborator Author

jeltsch commented Sep 24, 2024

Let’s see if the builds succeed now.

They do. 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants