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 Reset and PrepareForAssert methods #16

Merged
merged 8 commits into from
Oct 19, 2017

Conversation

mikhailkolesnik
Copy link
Contributor

This enables tests for code that uses TritonD client in async way
to synchronize on number of messages written.

This enables tests for code that uses TritonD client in async way
to synchronize on number of messages written.
@mikhailkolesnik
Copy link
Contributor Author

I created an issue to address the problem in general: #17

tritond/mock.go Outdated
c.lock.Unlock()
//Code that uses TritonD client in async way might want to able to block till Put is finished for testing
go func() { c.Channel <- data }()
c.Lock.Unlock()

Choose a reason for hiding this comment

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

I know this isn't your code, but is there any reason why this isn't defer c.Lock.Unlock and moved to right after the c.Lock.Lock() statement?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed

We need reset method as quite often test clients are created once for
test package and the same client is reused across multiple tests.
It might be handy to reset client so net effect of one test can be
evaluated.

In async usages of TritonD client we need to make sure we yield to
goroutines so that logging is actually complete
and that we synchronize assertion code so that race detector doesn't
complain about it.
We need reset method as quite often test clients are created once for
test package and the same client is reused across multiple tests.
It might be handy to reset client so net effect of one test can be
evaluated.

In async usages of TritonD client we need to make sure we yield to
goroutines so that logging is actually complete
and that we synchronize assertion code so that race detector doesn't
complain about it.
@mikhailkolesnik
Copy link
Contributor Author

@cvanderschuere Do you know why circle is failing for this branch?
It says something about go get...

@mikhailkolesnik mikhailkolesnik changed the title Add a channel to which events are set on put Add Reset and PrepareForAssert methods Oct 18, 2017
@@ -37,6 +38,26 @@ func (c *MockClient) Close(ctx context.Context) error {
return nil
}

// Reset resets MockClient to the initial state
func (c *MockClient) Reset() {
c.lock.Lock()

Choose a reason for hiding this comment

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

won't this block if the lock is held by another, so a call to Reset could result in a deadlock?

Choose a reason for hiding this comment

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

Still thinking this will block if another context has the client holding the lock.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Since we have only one lock - it should not cause any deadlock. As who ever holds it should eventually let it go.

@@ -80,11 +81,11 @@ func (c *consumer) Start() error {
}
}
}()
runtime.Gosched()
Copy link
Contributor

Choose a reason for hiding this comment

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

We should try and avoid this if possible and It's not needed in this case

@@ -21,7 +21,7 @@ func TestPut(t *testing.T) {
data := map[string]interface{}{
"object_type": "delivery",
"delivery_uuid": "example-delivery-uuid",
"ts": time.Now(),
"ts": time.Now().Round(0),
Copy link
Contributor

Choose a reason for hiding this comment

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

Truncate?

}

if err = c.socket.Bind("tcp://127.0.0.1:3515"); err != nil {
panic(err)
Copy link
Contributor

Choose a reason for hiding this comment

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

This error is much harder to deal with than the previous serial version.

Choose a reason for hiding this comment

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

why not just return the err on a channel (or put it in an error slice) and wait for all go routines to finish then check the error and return it?


return nil
}

func (c *consumer) Stop() error {
func (c *consumer) Stop() {
close(c.close)
Copy link
Contributor

Choose a reason for hiding this comment

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

This can also be solved by requiring callers to do this on the same goroutine right?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No. The problem is that the read happens on the different one. So close must happen on the same one that the read and create happens on.

Copy link
Contributor

Choose a reason for hiding this comment

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

Realized this is only for the test client so this is much less important

func (c *MockClient) PrepareForAssert() func() {
runtime.Gosched()
c.lock.Lock()
return c.unlock
Copy link
Contributor

Choose a reason for hiding this comment

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

Personal preference would be to use an anonymous function here so it can be very specific to this use case.

Choose a reason for hiding this comment

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

Also, not sure if you really want runtime.Gosched(). It looks like that forces a context switch, which might not be what you want?
https://stackoverflow.com/questions/13107958/what-exactly-does-runtime-gosched-do

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The idea is to make it reusable for all cases when clients want to test async usages of this code. Anonymous func in my code is not reusable.

Copy link
Contributor

@cvanderschuere cvanderschuere left a comment

Choose a reason for hiding this comment

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

LGTM

We should continue to iterate on testing patterns here, but this should work


return nil
}

func (c *consumer) Stop() error {
func (c *consumer) Stop() {
close(c.close)
Copy link
Contributor

Choose a reason for hiding this comment

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

Realized this is only for the test client so this is much less important


if err = c.socket.Bind("tcp://127.0.0.1:3515"); err != nil {
return err
}

go func() {
Copy link
Contributor

Choose a reason for hiding this comment

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

A bit of a weird pattern, but works

@mikhailkolesnik mikhailkolesnik merged commit 01c188d into master Oct 19, 2017
@mikhailkolesnik mikhailkolesnik deleted the mkolesnik/MockClient_Async branch October 19, 2017 23:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants