summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2024-01-29 02:42:51 +0700
committerShulhan <ms@kilabit.info>2024-01-29 02:43:44 +0700
commite33a335cd730748517b0bcde34c68e982205f5fa (patch)
treee4d977b662412ff6dc0a0d883fa1849efc352bda
parent137d8746c608a19c14f619fc796241d4c416e812 (diff)
downloadpakakeh.go-e33a335cd730748517b0bcde34c68e982205f5fa.tar.xz
test/mock: implement mock for crypto [rand.Reader]
The RandReader implement [io.Reader]. To provide predictable result, the RandReader is seeded with slice of bytes. A call to Read will fill the passed bytes with those seed. For example, given seed as "abc" (length is three), calling Read with bytes length five will return "abcab".
-rw-r--r--lib/test/mock/mock.go2
-rw-r--r--lib/test/mock/rand_reader.go51
-rw-r--r--lib/test/mock/rand_reader_example_test.go41
3 files changed, 93 insertions, 1 deletions
diff --git a/lib/test/mock/mock.go b/lib/test/mock/mock.go
index 5ab5f924..23da6c21 100644
--- a/lib/test/mock/mock.go
+++ b/lib/test/mock/mock.go
@@ -3,7 +3,7 @@
// license that can be found in the LICENSE file.
// Package mock provide a mocking for standard input, standard output,
-// standard error, and io.ReadWriter.
+// standard error, io.ReadWriter, and [rand.Reader].
package mock
import (
diff --git a/lib/test/mock/rand_reader.go b/lib/test/mock/rand_reader.go
new file mode 100644
index 00000000..aebc3260
--- /dev/null
+++ b/lib/test/mock/rand_reader.go
@@ -0,0 +1,51 @@
+// Copyright 2024, Shulhan <ms@kilabit.info>. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mock
+
+// RandReader implement [io.Reader] for mocking crypto [rand.Reader].
+// To provide predictable result, the RandReader is seeded with the same
+// slice of bytes.
+// A call to Read will fill the passed bytes with those seed.
+type RandReader struct {
+ seed []byte
+ counter int
+}
+
+// NewRandReader create new random reader using seed as generator.
+// The longer the seed, the longer the random values become unique.
+func NewRandReader(seed []byte) (r *RandReader) {
+ r = &RandReader{
+ seed: seed,
+ }
+ return r
+}
+
+// Read fill the raw bytes with seed.
+// If raw length larger than the seed, it will be filled with the same seed
+// until all bytes filled.
+//
+// For example, given seed as "abc" (length is three), and raw length is
+// five, then Read will return "abcab".
+func (rr *RandReader) Read(raw []byte) (n int, err error) {
+ var (
+ expn = len(raw)
+
+ nwrite int
+ )
+
+ for n < expn {
+ nwrite = copy(raw[n:], rr.seed[rr.counter:])
+ n += nwrite
+ }
+
+ // Increment the counter to make the seed start from next byte, so
+ // the next Read will return different result but still predictable.
+ rr.counter++
+ if rr.counter == len(rr.seed) {
+ rr.counter = 0
+ }
+
+ return n, nil
+}
diff --git a/lib/test/mock/rand_reader_example_test.go b/lib/test/mock/rand_reader_example_test.go
new file mode 100644
index 00000000..7aa1dd26
--- /dev/null
+++ b/lib/test/mock/rand_reader_example_test.go
@@ -0,0 +1,41 @@
+// Copyright 2024, Shulhan <ms@kilabit.info>. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package mock_test
+
+import (
+ "crypto/rand"
+ "fmt"
+ "log"
+
+ "github.com/shuLhan/share/lib/test/mock"
+)
+
+func ExampleRandReader() {
+ var (
+ seed = []byte(`123`)
+ rr = mock.NewRandReader(seed)
+ b = make([]byte, 8)
+
+ x int
+ n int
+ err error
+ )
+
+ rand.Reader = rr
+
+ for x = 0; x <= len(seed); x++ {
+ n, err = rand.Read(b)
+ if err != nil {
+ log.Fatal(err)
+ }
+ fmt.Println(n, string(b))
+ }
+
+ // Output:
+ // 8 12312312
+ // 8 23232323
+ // 8 33333333
+ // 8 12312312
+}