-
Notifications
You must be signed in to change notification settings - Fork 205
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'rc/v1.5.0' into add-unit-tests-for-node-package
- Loading branch information
Showing
88 changed files
with
898 additions
and
806 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
package errChan | ||
|
||
import "sync" | ||
|
||
type errChanWrapper struct { | ||
ch chan error | ||
closed bool | ||
closeMutex sync.RWMutex | ||
} | ||
|
||
// NewErrChanWrapper creates a new errChanWrapper | ||
func NewErrChanWrapper() *errChanWrapper { | ||
return &errChanWrapper{ | ||
ch: make(chan error, 1), | ||
closed: false, | ||
} | ||
} | ||
|
||
// WriteInChanNonBlocking will send the given error on the channel if the chan is not blocked | ||
func (ec *errChanWrapper) WriteInChanNonBlocking(err error) { | ||
ec.closeMutex.RLock() | ||
defer ec.closeMutex.RUnlock() | ||
|
||
if ec.closed { | ||
return | ||
} | ||
|
||
select { | ||
case ec.ch <- err: | ||
default: | ||
} | ||
} | ||
|
||
// ReadFromChanNonBlocking will read from the channel, or return nil if no error was sent on the channel | ||
func (ec *errChanWrapper) ReadFromChanNonBlocking() error { | ||
select { | ||
case err := <-ec.ch: | ||
return err | ||
default: | ||
return nil | ||
} | ||
} | ||
|
||
// Close will close the channel | ||
func (ec *errChanWrapper) Close() { | ||
ec.closeMutex.Lock() | ||
defer ec.closeMutex.Unlock() | ||
|
||
if ec.closed { | ||
return | ||
} | ||
|
||
if ec.ch == nil { | ||
return | ||
} | ||
|
||
close(ec.ch) | ||
ec.closed = true | ||
} | ||
|
||
// Len returns the length of the channel | ||
func (ec *errChanWrapper) Len() int { | ||
return len(ec.ch) | ||
} | ||
|
||
// IsInterfaceNil returns true if there is no value under the interface | ||
func (ec *errChanWrapper) IsInterfaceNil() bool { | ||
return ec == nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package errChan | ||
|
||
import ( | ||
"fmt" | ||
"sync" | ||
"testing" | ||
|
||
"github.com/multiversx/mx-chain-core-go/core/check" | ||
"github.com/stretchr/testify/assert" | ||
) | ||
|
||
func TestNewErrChan(t *testing.T) { | ||
t.Parallel() | ||
|
||
ec := NewErrChanWrapper() | ||
assert.False(t, check.IfNil(ec)) | ||
assert.Equal(t, 1, cap(ec.ch)) | ||
} | ||
|
||
func TestErrChan_WriteInChanNonBlocking(t *testing.T) { | ||
t.Parallel() | ||
|
||
t.Run("write in a nil channel", func(t *testing.T) { | ||
t.Parallel() | ||
|
||
ec := NewErrChanWrapper() | ||
ec.ch = nil | ||
ec.WriteInChanNonBlocking(fmt.Errorf("err1")) | ||
|
||
assert.Equal(t, 0, len(ec.ch)) | ||
}) | ||
|
||
t.Run("write in a closed channel", func(t *testing.T) { | ||
t.Parallel() | ||
|
||
ec := NewErrChanWrapper() | ||
ec.Close() | ||
ec.WriteInChanNonBlocking(fmt.Errorf("err1")) | ||
|
||
assert.Equal(t, 0, len(ec.ch)) | ||
}) | ||
|
||
t.Run("should work", func(t *testing.T) { | ||
expectedErr := fmt.Errorf("err1") | ||
ec := NewErrChanWrapper() | ||
ec.WriteInChanNonBlocking(expectedErr) | ||
ec.WriteInChanNonBlocking(fmt.Errorf("err2")) | ||
ec.WriteInChanNonBlocking(fmt.Errorf("err3")) | ||
|
||
assert.Equal(t, 1, len(ec.ch)) | ||
assert.Equal(t, expectedErr, <-ec.ch) | ||
assert.Equal(t, 0, len(ec.ch)) | ||
}) | ||
} | ||
|
||
func TestErrChan_ReadFromChanNonBlocking(t *testing.T) { | ||
t.Parallel() | ||
|
||
expectedErr := fmt.Errorf("err1") | ||
ec := NewErrChanWrapper() | ||
ec.ch <- expectedErr | ||
|
||
assert.Equal(t, 1, len(ec.ch)) | ||
assert.Equal(t, expectedErr, ec.ReadFromChanNonBlocking()) | ||
assert.Equal(t, 0, len(ec.ch)) | ||
assert.Nil(t, ec.ReadFromChanNonBlocking()) | ||
} | ||
|
||
func TestErrChan_Close(t *testing.T) { | ||
t.Parallel() | ||
|
||
t.Run("close an already closed channel", func(t *testing.T) { | ||
t.Parallel() | ||
|
||
ec := NewErrChanWrapper() | ||
ec.Close() | ||
|
||
assert.True(t, ec.closed) | ||
ec.Close() | ||
}) | ||
|
||
t.Run("close a nil channel", func(t *testing.T) { | ||
t.Parallel() | ||
|
||
ec := NewErrChanWrapper() | ||
ec.ch = nil | ||
ec.Close() | ||
|
||
assert.False(t, ec.closed) | ||
}) | ||
} | ||
|
||
func TestErrChan_Len(t *testing.T) { | ||
t.Parallel() | ||
|
||
ec := NewErrChanWrapper() | ||
assert.Equal(t, 0, ec.Len()) | ||
|
||
ec.ch <- fmt.Errorf("err1") | ||
assert.Equal(t, 1, ec.Len()) | ||
|
||
ec.WriteInChanNonBlocking(fmt.Errorf("err2")) | ||
assert.Equal(t, 1, ec.Len()) | ||
} | ||
|
||
func TestErrChan_ConcurrentOperations(t *testing.T) { | ||
t.Parallel() | ||
|
||
ec := NewErrChanWrapper() | ||
numOperations := 1000 | ||
numMethods := 2 | ||
wg := sync.WaitGroup{} | ||
wg.Add(numOperations) | ||
for i := 0; i < numOperations; i++ { | ||
go func(idx int) { | ||
|
||
if idx == numOperations-100 { | ||
ec.Close() | ||
} | ||
|
||
operation := idx % numMethods | ||
switch operation { | ||
case 0: | ||
ec.WriteInChanNonBlocking(fmt.Errorf("err")) | ||
case 1: | ||
_ = ec.ReadFromChanNonBlocking() | ||
default: | ||
assert.Fail(t, "invalid numMethods") | ||
} | ||
|
||
wg.Done() | ||
}(i) | ||
} | ||
|
||
wg.Wait() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.