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

Write FIFO cache unit tests #1201

Merged
merged 17 commits into from
Sep 30, 2024
Merged

Write FIFO cache unit tests #1201

merged 17 commits into from
Sep 30, 2024

Conversation

iFrostizz
Copy link
Contributor

No description provided.

@iFrostizz iFrostizz self-assigned this Jul 26, 2024
cache/fifo_test.go Outdated Show resolved Hide resolved
Comment on lines 33 to 42
limit: 10,
maxVal: 10,
check: func(t *testing.T, cache *FIFO[int, int]) {
require := require.New(t)
_, ok := cache.Get(0)
require.False(ok)
v, ok := cache.Get(1)
require.True(ok)
require.Equal(1, v)
},
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 these tests are on the right track but still find that these are a little hard to reason about (particularly the limit/maxval) parameter are not obvious on how they work until you read the test body.

I think one way we could make this cleaner (and remove the check field) would be to make a struct like so:

func TestFIFOCache(t *testing.T) {
...
type put struct {
    i     int
    ok  bool
}

type get struct {
    i     int
    ok  bool
}

and if we did this I think we could write tests as:

{
    puts:[]put{
        {i: 1, ok: true}
        {i: 1, ok: false}
    }
    gets:[]get{
        {i: 1,	ok: true}
    }
}

Copy link
Collaborator

Choose a reason for hiding this comment

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

This structure looks like a nice improvement. This should make it a bit more readable and we can just use a size like 2, so it's not excessive.

I think we should test the following cases here:

  • no elements removed when the cache is less than full
  • no elements removed when cache is exactly full
  • elements removed in FIFO order when cache overfills
  • elements removed in FIFO order after additional get/put ops for element to be removed FIFO

I think we're currently missing the last case. There's a unit test to make sure if we insert the first element again, then it stays in the cache, but we should additionally test that this does not change its position in the queue for removal to differentiate FIFO from LRU.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks both !
I have changed the test suite to only have a name, osp pairs and it's way more compact/readable.
Also added tests cases to cover @aaronbuchwald ones, haven't implemented the last one for now (TODO!)

Copy link
Contributor 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 if there is a real difference between the two last test cases, the case "elements removed in FIFO order when cache overfills" seems to fulfil both, please tell me if that's wrong.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually they are different, see the test case "elements removed in FIFO order and not LRU".

maxVal: 8,
check: func(t *testing.T, cache *FIFO[int, int]) {
require := require.New(t)
exists := cache.Put(9, 9)
Copy link
Contributor

Choose a reason for hiding this comment

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

Usually it's idiomatic to use ok in Go instead of exists

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think that we should only use ok instead of exists for Get because ok seems to imply that something can go wrong while it just means that the value is already in the cache so no need to insert it again. It seems like ok could be used if the cache does not support overwriting value for instance.

require := require.New(t)

cache, err := NewFIFO[int, int](tt.limit)
require.Equal(tt.expected, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: use ErrorIs. This does a match to check if the error was wrapped instead of just the text which is more durable (ref)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can't use ErrorIs, the error that says "maxSize must be greater than 0" is private and cannot be imported. It's defined in https://github.com/ava-labs/avalanchego/blob/321e727328a86bcfdb8f5bef164e7d50e698408b/utils/buffer/bounded_nonblocking_queue.go#L11
This error check has been moved to a unit test TestEmptyCacheFails that checks that this error occurs when the cache is initialized with a length of 0, so it's better contained.

cache/fifo_test.go Outdated Show resolved Hide resolved
aaronbuchwald
aaronbuchwald previously approved these changes Aug 13, 2024
@aaronbuchwald aaronbuchwald enabled auto-merge (squash) August 13, 2024 23:31
@aaronbuchwald aaronbuchwald enabled auto-merge (squash) August 13, 2024 23:31
@aaronbuchwald aaronbuchwald merged commit e78841e into main Sep 30, 2024
17 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: Done ✅
Development

Successfully merging this pull request may close these issues.

3 participants