diff --git a/pkg/network/dialer/dialer_test.go b/pkg/network/dialer/dialer_test.go new file mode 100644 index 000000000..5b9425551 --- /dev/null +++ b/pkg/network/dialer/dialer_test.go @@ -0,0 +1,57 @@ +/* + * Copyright 2022 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package dialer + +import ( + "crypto/tls" + "errors" + "github.com/cloudwego/hertz/pkg/common/test/assert" + "github.com/cloudwego/hertz/pkg/network" + "net" + "testing" + "time" +) + +func TestDialer(t *testing.T) { + SetDialer(&mockDialer{}) + dialer := DefaultDialer() + assert.DeepEqual(t, &mockDialer{}, dialer) + + _, err := AddTLS(nil, nil) + assert.NotNil(t, err) + + _, err = DialConnection("", "", 0, nil) + assert.NotNil(t, err) + + _, err = DialTimeout("", "", 0, nil) + assert.NotNil(t, err) +} + +type mockDialer struct { +} + +func (m *mockDialer) DialConnection(network, address string, timeout time.Duration, tlsConfig *tls.Config) (conn network.Conn, err error) { + return nil, errors.New("method not implement") +} + +func (m *mockDialer) DialTimeout(network, address string, timeout time.Duration, tlsConfig *tls.Config) (conn net.Conn, err error) { + return nil, errors.New("method not implement") +} + +func (m *mockDialer) AddTLS(conn network.Conn, tlsConfig *tls.Config) (network.Conn, error) { + return nil, errors.New("method not implement") +} diff --git a/pkg/network/netpoll/connection_test.go b/pkg/network/netpoll/connection_test.go new file mode 100644 index 000000000..36e3cc900 --- /dev/null +++ b/pkg/network/netpoll/connection_test.go @@ -0,0 +1,204 @@ +/* + * Copyright 2022 CloudWeGo Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package netpoll + +import ( + "errors" + "github.com/cloudwego/hertz/pkg/common/test/assert" + "github.com/cloudwego/netpoll" + "net" + "testing" + "time" +) + +func TestReadBytes(t *testing.T) { + c := &mockConn{[]byte("abcdefg"), nil, 0} + conn := newConn(c) + assert.DeepEqual(t, 7, conn.Len()) + + b, _ := conn.Peek(1) + assert.DeepEqual(t, []byte{'a'}, b) + + readByte, _ := conn.ReadByte() + assert.DeepEqual(t, byte('a'), readByte) + + readBinary, _ := conn.ReadBinary(2) + assert.DeepEqual(t, []byte{'b', 'c'}, readBinary) +} + +func TestPeekRelease(t *testing.T) { + c := &mockConn{[]byte("abcdefg"), nil, 0} + conn := newConn(c) + + // release the buf + conn.Release() + _, err := conn.Peek(1) + assert.DeepEqual(t, errors.New("peek error"), err) + + assert.DeepEqual(t, errors.New("skip error"), conn.Skip(2)) +} + +func TestWriteLogin(t *testing.T) { + c := &mockConn{nil, []byte("abcdefg"), 0} + conn := newConn(c) + buf, _ := conn.Malloc(10) + assert.DeepEqual(t, 10, len(buf)) + n, _ := conn.WriteBinary([]byte("abcdefg")) + assert.DeepEqual(t, 7, n) + assert.DeepEqual(t, errors.New("flush error"), conn.Flush()) +} + +func TestHandleSpecificError(t *testing.T) { + conn := &Conn{} + assert.DeepEqual(t, false, conn.HandleSpecificError(nil, "")) + assert.DeepEqual(t, true, conn.HandleSpecificError(netpoll.ErrConnClosed, "")) +} + +type mockConn struct { + readBuf []byte + writeBuf []byte + // index for the first readable byte in readBuf + off int +} + +// mockConn's methods is simplified for unit test +// Peek returns the next n bytes without advancing the reader +func (m *mockConn) Peek(n int) (b []byte, err error) { + if m.off+n < len(m.readBuf) { + return m.readBuf[m.off : m.off+n], nil + } + return nil, errors.New("peek error") +} + +// Skip discards the next n bytes +func (m *mockConn) Skip(n int) error { + if m.off+n < len(m.readBuf) { + m.off += n + return nil + } + return errors.New("skip error") +} + +// Release the memory space occupied by all read slices +func (m *mockConn) Release() error { + m.readBuf = nil + m.off = 0 + return nil +} + +// Len returns the total length of the readable data in the reader +func (m *mockConn) Len() int { + return len(m.readBuf) - m.off +} + +// ReadByte is used to read one byte with advancing the read pointer +func (m *mockConn) ReadByte() (byte, error) { + if m.off < len(m.readBuf) { + m.off++ + return m.readBuf[m.off-1], nil + } + return 0, errors.New("readByte error") +} + +// ReadBinary is used to read next n byte with copy, and the read pointer will be advanced +func (m *mockConn) ReadBinary(n int) (b []byte, err error) { + if m.off+n < len(m.readBuf) { + m.off += n + return m.readBuf[m.off-n : m.off], nil + } + return nil, errors.New("readByte error") +} + +// Malloc will provide a n bytes buffer to send data +func (m *mockConn) Malloc(n int) (buf []byte, err error) { + m.writeBuf = make([]byte, n) + return m.writeBuf, nil +} + +// WriteBinary will use the user buffer to flush +func (m *mockConn) WriteBinary(b []byte) (n int, err error) { + return len(b), nil +} + +// Flush will send data to the peer end +func (m *mockConn) Flush() error { + return errors.New("flush error") +} + +func (m *mockConn) HandleSpecificError(err error, rip string) (needIgnore bool) { + panic("implement me") +} + +func (m *mockConn) Read(b []byte) (n int, err error) { + panic("implement me") +} + +func (m *mockConn) Write(b []byte) (n int, err error) { + panic("implement me") +} + +func (m *mockConn) Close() error { + panic("implement me") +} + +func (m *mockConn) LocalAddr() net.Addr { + panic("implement me") +} + +func (m *mockConn) RemoteAddr() net.Addr { + panic("implement me") +} + +func (m *mockConn) SetDeadline(deadline time.Time) error { + panic("implement me") +} + +func (m *mockConn) SetReadDeadline(deadline time.Time) error { + panic("implement me") +} + +func (m *mockConn) SetWriteDeadline(deadline time.Time) error { + panic("implement me") +} + +func (m *mockConn) Reader() netpoll.Reader { + panic("implement me") +} + +func (m *mockConn) Writer() netpoll.Writer { + panic("implement me") +} + +func (m *mockConn) IsActive() bool { + panic("implement me") +} + +func (m *mockConn) SetReadTimeout(timeout time.Duration) error { + panic("implement me") +} + +func (m *mockConn) SetIdleTimeout(timeout time.Duration) error { + panic("implement me") +} + +func (m *mockConn) SetOnRequest(on netpoll.OnRequest) error { + panic("implement me") +} + +func (m *mockConn) AddCloseCallback(callback netpoll.CloseCallback) error { + panic("implement me") +} diff --git a/pkg/network/standard/connection_test.go b/pkg/network/standard/connection_test.go index 6909d9fe9..e90485b39 100644 --- a/pkg/network/standard/connection_test.go +++ b/pkg/network/standard/connection_test.go @@ -18,13 +18,14 @@ package standard import ( "bytes" + "crypto/tls" + "errors" + "github.com/cloudwego/hertz/pkg/common/test/assert" "io" "net" "strings" "testing" "time" - - "github.com/cloudwego/hertz/pkg/common/test/assert" ) func TestRead(t *testing.T) { @@ -231,8 +232,48 @@ func TestWriteLogic(t *testing.T) { } } +func TestInitializeConn(t *testing.T) { + c := mockConn{ + localAddr: &mockAddr{ + network: "tcp", + address: "192.168.0.10:80", + }, + remoteAddr: &mockAddr{ + network: "tcp", + address: "192.168.0.20:80", + }, + } + conn := newConn(&c, 8192) + // check the assignment + assert.DeepEqual(t, errors.New("conn: deadline not supported"), conn.SetDeadline(time.Time{})) + assert.DeepEqual(t, errors.New("conn: deadline not supported"), conn.SetReadDeadline(time.Time{})) + assert.DeepEqual(t, errors.New("conn: deadline not supported"), conn.SetWriteDeadline(time.Time{})) + assert.DeepEqual(t, errors.New("conn: deadline not supported"), conn.SetReadTimeout(time.Duration(1)*time.Second)) + assert.DeepEqual(t, errors.New("conn: deadline not supported"), conn.SetReadTimeout(time.Duration(-1)*time.Second)) + assert.DeepEqual(t, errors.New("conn: method not supported"), conn.Close()) + assert.DeepEqual(t, &mockAddr{network: "tcp", address: "192.168.0.10:80"}, conn.LocalAddr()) + assert.DeepEqual(t, &mockAddr{network: "tcp", address: "192.168.0.20:80"}, conn.RemoteAddr()) +} + +func TestInitializeTLSConn(t *testing.T) { + c := mockConn{} + tlsConn := newTLSConn(&c, 8192).(*TLSConn) + assert.DeepEqual(t, errors.New("conn: method not supported"), tlsConn.Handshake()) + assert.DeepEqual(t, tls.ConnectionState{}, tlsConn.ConnectionState()) +} + type mockConn struct { - buffer bytes.Buffer + buffer bytes.Buffer + localAddr net.Addr + remoteAddr net.Addr +} + +func (m *mockConn) Handshake() error { + return errors.New("conn: method not supported") +} + +func (m *mockConn) ConnectionState() tls.ConnectionState { + return tls.ConnectionState{} } func (m mockConn) Read(b []byte) (n int, err error) { @@ -243,7 +284,6 @@ func (m mockConn) Read(b []byte) (n int, err error) { if len(b) < 1024 { return 100, nil } - if len(b) < 5000 { return 4096, nil } @@ -255,26 +295,42 @@ func (m *mockConn) Write(b []byte) (n int, err error) { return m.buffer.Write(b) } -func (m mockConn) Close() error { - panic("implement me") +func (m *mockConn) Close() error { + return errors.New("conn: method not supported") +} + +func (m *mockConn) LocalAddr() net.Addr { + return m.localAddr +} + +func (m *mockConn) RemoteAddr() net.Addr { + return m.remoteAddr +} + +func (m *mockConn) SetDeadline(deadline time.Time) error { + if err := m.SetWriteDeadline(deadline); err != nil { + return err + } + return m.SetWriteDeadline(deadline) } -func (m mockConn) LocalAddr() net.Addr { - panic("implement me") +func (m *mockConn) SetReadDeadline(deadline time.Time) error { + return errors.New("conn: deadline not supported") } -func (m mockConn) RemoteAddr() net.Addr { - panic("implement me") +func (m *mockConn) SetWriteDeadline(deadline time.Time) error { + return errors.New("conn: deadline not supported") } -func (m mockConn) SetDeadline(t time.Time) error { - panic("implement me") +type mockAddr struct { + network string + address string } -func (m mockConn) SetReadDeadline(t time.Time) error { - panic("implement me") +func (m *mockAddr) Network() string { + return m.network } -func (m mockConn) SetWriteDeadline(t time.Time) error { - panic("implement me") +func (m *mockAddr) String() string { + return m.address }