Skip to content

Commit cbb52b9

Browse files
committed
conntest: Add 100% coverage
- conntest: Small coherency fixes along the way. - conntest: Add Discard. Useful for zero filled tests. - reg: Improve testing. - CONTRIBUTING.md: fix a typo.
1 parent 778d319 commit cbb52b9

File tree

4 files changed

+285
-115
lines changed

4 files changed

+285
-115
lines changed

CONTRIBUTING.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
# Contributing
22

3-
Thanks for contributing to the project! Please look at [periph the
4-
contribution guidelines](https://periph.io/project/contributing/) first.
3+
Thanks for contributing to the project! Please look at [the periph contribution
4+
guidelines](https://periph.io/project/contributing/) first.

conn/conntest/conntest.go

+36-29
Original file line numberDiff line numberDiff line change
@@ -19,33 +19,23 @@ import (
1919
type RecordRaw struct {
2020
sync.Mutex
2121
W io.Writer
22-
D conn.Duplex
2322
}
2423

2524
func (r *RecordRaw) String() string {
2625
return "recordraw"
2726
}
2827

29-
// Write implements conn.Conn.
30-
func (r *RecordRaw) Write(b []byte) (int, error) {
31-
r.Lock()
32-
defer r.Unlock()
33-
return r.W.Write(b)
34-
}
35-
3628
// Tx implements conn.Conn.
3729
func (r *RecordRaw) Tx(w, read []byte) error {
3830
if len(read) != 0 {
3931
return errors.New("conntest: not implemented")
4032
}
41-
_, err := r.Write(w)
33+
_, err := r.W.Write(w)
4234
return err
4335
}
4436

4537
func (r *RecordRaw) Duplex() conn.Duplex {
46-
r.Lock()
47-
defer r.Unlock()
48-
return r.D
38+
return conn.Half
4939
}
5040

5141
// IO registers the I/O that happened on either a real or fake connection.
@@ -61,21 +51,12 @@ type Record struct {
6151
sync.Mutex
6252
Conn conn.Conn // Conn can be nil if only writes are being recorded.
6353
Ops []IO
64-
D conn.Duplex
6554
}
6655

6756
func (r *Record) String() string {
6857
return "record"
6958
}
7059

71-
// Write implements conn.Conn.
72-
func (r *Record) Write(d []byte) (int, error) {
73-
if err := r.Tx(d, nil); err != nil {
74-
return 0, err
75-
}
76-
return len(d), nil
77-
}
78-
7960
// Tx implements conn.Conn.
8061
func (r *Record) Tx(w, read []byte) error {
8162
r.Lock()
@@ -100,9 +81,10 @@ func (r *Record) Tx(w, read []byte) error {
10081
}
10182

10283
func (r *Record) Duplex() conn.Duplex {
103-
r.Lock()
104-
defer r.Unlock()
105-
return r.D
84+
if r.Conn != nil {
85+
return r.Conn.Duplex()
86+
}
87+
return conn.DuplexUnknown
10688
}
10789

10890
// Playback implements conn.Conn and plays back a recorded I/O flow.
@@ -119,12 +101,14 @@ func (p *Playback) String() string {
119101
return "playback"
120102
}
121103

122-
// Write implements conn.Conn.
123-
func (p *Playback) Write(d []byte) (int, error) {
124-
if err := p.Tx(d, nil); err != nil {
125-
return 0, err
104+
// Close verifies that all the expected Ops have been consumed.
105+
func (p *Playback) Close() error {
106+
p.Lock()
107+
defer p.Unlock()
108+
if len(p.Ops) != 0 {
109+
return fmt.Errorf("conntest: expected playback to be empty:\n%#v", p.Ops)
126110
}
127-
return len(d), nil
111+
return nil
128112
}
129113

130114
// Tx implements conn.Conn.
@@ -151,6 +135,29 @@ func (p *Playback) Duplex() conn.Duplex {
151135
return p.D
152136
}
153137

138+
// Discard implements conn.Conn and discards all writes and reads zeros. It
139+
// never fails.
140+
type Discard struct {
141+
D conn.Duplex
142+
}
143+
144+
func (d *Discard) String() string {
145+
return "discard"
146+
}
147+
148+
func (d *Discard) Tx(w, r []byte) error {
149+
for i := range r {
150+
r[i] = 0
151+
}
152+
return nil
153+
}
154+
155+
func (d *Discard) Duplex() conn.Duplex {
156+
return d.D
157+
}
158+
159+
//
160+
154161
var _ conn.Conn = &RecordRaw{}
155162
var _ conn.Conn = &Record{}
156163
var _ conn.Conn = &Playback{}

conn/conntest/conntest_test.go

+154
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// Copyright 2017 The Periph Authors. All rights reserved.
2+
// Use of this source code is governed under the Apache License, Version 2.0
3+
// that can be found in the LICENSE file.
4+
5+
package conntest
6+
7+
import (
8+
"bytes"
9+
"testing"
10+
11+
"periph.io/x/periph/conn"
12+
)
13+
14+
func TestRecordRaw(t *testing.T) {
15+
b := bytes.Buffer{}
16+
r := RecordRaw{W: &b}
17+
if d := r.Duplex(); d != conn.Half {
18+
t.Fatal(d)
19+
}
20+
if s := r.String(); s != "recordraw" {
21+
t.Fatal(s)
22+
}
23+
if r.Tx(nil, []byte{0}) == nil {
24+
t.Fatal("cannot accept read buffer")
25+
}
26+
if err := r.Tx([]byte{'a'}, nil); err != nil {
27+
t.Fatal(err)
28+
}
29+
if s := b.String(); s != "a" {
30+
t.Fatal(s)
31+
}
32+
}
33+
34+
func TestRecord_empty(t *testing.T) {
35+
r := Record{}
36+
if s := r.String(); s != "record" {
37+
t.Fatal(s)
38+
}
39+
if r.Tx(nil, []byte{'a'}) == nil {
40+
t.Fatal("Bus is nil")
41+
}
42+
if d := r.Duplex(); d != conn.DuplexUnknown {
43+
t.Fatal(d)
44+
}
45+
}
46+
47+
func TestRecord_empty_tx(t *testing.T) {
48+
r := Record{}
49+
if err := r.Tx(nil, nil); err != nil {
50+
t.Fatal(err)
51+
}
52+
if len(r.Ops) != 1 {
53+
t.Fatal(r.Ops)
54+
}
55+
if err := r.Tx([]byte{'a', 'b'}, nil); err != nil {
56+
t.Fatal(err)
57+
}
58+
if len(r.Ops) != 2 {
59+
t.Fatal(r.Ops)
60+
}
61+
if r.Tx([]byte{'a', 'b'}, []byte{'d'}) == nil {
62+
t.Fatal("Bus is nil")
63+
}
64+
if len(r.Ops) != 2 {
65+
t.Fatal(r.Ops)
66+
}
67+
}
68+
69+
func TestPlayback(t *testing.T) {
70+
p := Playback{}
71+
if s := p.String(); s != "playback" {
72+
t.Fatal(s)
73+
}
74+
if err := p.Close(); err != nil {
75+
t.Fatal(err)
76+
}
77+
}
78+
79+
func TestPlayback_tx(t *testing.T) {
80+
p := Playback{
81+
Ops: []IO{
82+
{
83+
Write: []byte{10},
84+
Read: []byte{12},
85+
},
86+
},
87+
}
88+
if p.Tx(nil, nil) == nil {
89+
t.Fatal("missing read and write")
90+
}
91+
if p.Close() == nil {
92+
t.Fatal("Ops is not empty")
93+
}
94+
v := [1]byte{}
95+
if p.Tx([]byte{10}, make([]byte, 2)) == nil {
96+
t.Fatal("invalid read size")
97+
}
98+
if err := p.Tx([]byte{10}, v[:]); err != nil {
99+
t.Fatal(err)
100+
}
101+
if v[0] != 12 {
102+
t.Fatalf("expected 12, got %v", v)
103+
}
104+
if err := p.Tx([]byte{10}, v[:]); err == nil {
105+
t.Fatal("Playback.Ops is empty")
106+
}
107+
if err := p.Close(); err != nil {
108+
t.Fatal(err)
109+
}
110+
}
111+
112+
func TestRecord_Playback(t *testing.T) {
113+
r := Record{
114+
Conn: &Playback{
115+
Ops: []IO{
116+
{
117+
Write: []byte{10},
118+
Read: []byte{12},
119+
},
120+
},
121+
D: conn.Full,
122+
},
123+
}
124+
if d := r.Duplex(); d != conn.Full {
125+
t.Fatal(d)
126+
}
127+
128+
v := [1]byte{}
129+
if err := r.Tx([]byte{10}, v[:]); err != nil {
130+
t.Fatal(err)
131+
}
132+
if v[0] != 12 {
133+
t.Fatalf("expected 12, got %v", v)
134+
}
135+
if r.Tx([]byte{10}, v[:]) == nil {
136+
t.Fatal("Playback.Ops is empty")
137+
}
138+
}
139+
140+
func TestDiscard(t *testing.T) {
141+
d := Discard{D: conn.Half}
142+
if s := d.String(); s != "discard" {
143+
t.Fatal(s)
144+
}
145+
if v := d.Duplex(); v != conn.Half {
146+
t.Fatal(v)
147+
}
148+
if err := d.Tx(nil, nil); err != nil {
149+
t.Fatal(err)
150+
}
151+
if err := d.Tx([]byte{0}, []byte{0}); err != nil {
152+
t.Fatal(err)
153+
}
154+
}

0 commit comments

Comments
 (0)