github.com/blueinnovationsgroup/can-go@v0.0.0-20230518195432-d0567cda0028/pkg/socketcan/fileconn_test.go (about) 1 package socketcan 2 3 import ( 4 "fmt" 5 "net" 6 "os" 7 "testing" 8 "time" 9 10 "github.com/blueinnovationsgroup/can-go/internal/mocks/gen/mocksocketcan" 11 "github.com/golang/mock/gomock" 12 "gotest.tools/v3/assert" 13 ) 14 15 func TestUnwrapPathError(t *testing.T) { 16 innerErr := fmt.Errorf("inner error") 17 for _, tt := range []struct { 18 msg string 19 err error 20 expected error 21 }{ 22 { 23 msg: "no path error", 24 err: innerErr, 25 expected: innerErr, 26 }, 27 { 28 msg: "single path error", 29 err: &os.PathError{Op: "read", Err: innerErr}, 30 expected: innerErr, 31 }, 32 { 33 msg: "double path error", 34 err: &os.PathError{Op: "read", Err: &os.PathError{Op: "read", Err: innerErr}}, 35 expected: &os.PathError{Op: "read", Err: innerErr}, 36 }, 37 } { 38 tt := tt 39 t.Run(tt.msg, func(t *testing.T) { 40 assert.Error(t, unwrapPathError(tt.err), tt.expected.Error()) 41 }) 42 } 43 } 44 45 func TestFileConn_ReadWrite(t *testing.T) { 46 for _, tt := range []struct { 47 op string 48 fn func(file, []byte) (int, error) 49 mockFn func(*mocksocketcan.MockfileMockRecorder, interface{}) *gomock.Call 50 }{ 51 { 52 op: "read", 53 fn: file.Read, 54 mockFn: (*mocksocketcan.MockfileMockRecorder).Read, 55 }, 56 { 57 op: "write", 58 fn: file.Write, 59 mockFn: (*mocksocketcan.MockfileMockRecorder).Write, 60 }, 61 } { 62 tt := tt 63 t.Run(tt.op, func(t *testing.T) { 64 ctrl := gomock.NewController(t) 65 defer ctrl.Finish() 66 f := mocksocketcan.NewMockfile(ctrl) 67 fc := &fileConn{f: f, net: "can", ra: &canRawAddr{device: "can0"}} 68 t.Run("no error", func(t *testing.T) { 69 var data []byte 70 tt.mockFn(f.EXPECT(), data).Return(42, nil) 71 n, err := tt.fn(fc, data) 72 assert.Equal(t, 42, n) 73 assert.NilError(t, err) 74 }) 75 t.Run("error", func(t *testing.T) { 76 var data []byte 77 cause := fmt.Errorf("boom") 78 tt.mockFn(f.EXPECT(), data).Return(0, &os.PathError{Err: cause}) 79 n, err := tt.fn(fc, data) 80 assert.Equal(t, 0, n) 81 assert.ErrorContains(t, &net.OpError{Op: tt.op, Net: fc.net, Addr: fc.RemoteAddr(), Err: err}, "boom") 82 }) 83 }) 84 } 85 } 86 87 func TestFileConn_Addr(t *testing.T) { 88 fc := &fileConn{la: &canRawAddr{device: "can0"}, ra: &canRawAddr{device: "can1"}} 89 t.Run("local", func(t *testing.T) { 90 assert.Equal(t, fc.la, fc.LocalAddr()) 91 }) 92 t.Run("remote", func(t *testing.T) { 93 assert.Equal(t, fc.ra, fc.RemoteAddr()) 94 }) 95 } 96 97 func TestFileConn_SetDeadlines(t *testing.T) { 98 for _, tt := range []struct { 99 op string 100 fn func(file, time.Time) error 101 mockFn func(*mocksocketcan.MockfileMockRecorder, interface{}) *gomock.Call 102 }{ 103 { 104 op: "set deadline", 105 fn: file.SetDeadline, 106 mockFn: (*mocksocketcan.MockfileMockRecorder).SetDeadline, 107 }, 108 { 109 op: "set read deadline", 110 fn: file.SetReadDeadline, 111 mockFn: (*mocksocketcan.MockfileMockRecorder).SetReadDeadline, 112 }, 113 { 114 op: "set write deadline", 115 fn: file.SetWriteDeadline, 116 mockFn: (*mocksocketcan.MockfileMockRecorder).SetWriteDeadline, 117 }, 118 } { 119 tt := tt 120 t.Run(tt.op, func(t *testing.T) { 121 ctrl := gomock.NewController(t) 122 defer ctrl.Finish() 123 f := mocksocketcan.NewMockfile(ctrl) 124 fc := &fileConn{f: f, net: "can", ra: &canRawAddr{device: "can0"}} 125 t.Run("no error", func(t *testing.T) { 126 tt.mockFn(f.EXPECT(), time.Unix(0, 1)).Return(nil) 127 assert.NilError(t, tt.fn(fc, time.Unix(0, 1))) 128 }) 129 t.Run("error", func(t *testing.T) { 130 cause := fmt.Errorf("boom") 131 tt.mockFn(f.EXPECT(), time.Unix(0, 1)).Return(&os.PathError{Err: cause}) 132 err := tt.fn(fc, time.Unix(0, 1)) 133 assert.Error(t, err, (&net.OpError{Op: tt.op, Net: fc.net, Addr: fc.RemoteAddr(), Err: cause}).Error()) 134 }) 135 }) 136 } 137 } 138 139 func TestFileConn_Close(t *testing.T) { 140 ctrl := gomock.NewController(t) 141 defer ctrl.Finish() 142 f := mocksocketcan.NewMockfile(ctrl) 143 fc := &fileConn{f: f, net: "can", ra: &canRawAddr{device: "can0"}} 144 t.Run("no error", func(t *testing.T) { 145 f.EXPECT().Close().Return(nil) 146 assert.NilError(t, fc.Close()) 147 }) 148 t.Run("error", func(t *testing.T) { 149 cause := fmt.Errorf("boom") 150 f.EXPECT().Close().Return(&os.PathError{Err: cause}) 151 err := fc.Close() 152 assert.Error(t, err, (&net.OpError{Op: "close", Net: fc.net, Addr: fc.RemoteAddr(), Err: cause}).Error()) 153 }) 154 }