github.com/matrixorigin/matrixone@v1.2.0/pkg/frontend/iopackage_test.go (about)

     1  // Copyright 2021 Matrix Origin
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package frontend
    16  
    17  import (
    18  	"context"
    19  	"fmt"
    20  	"sync"
    21  	"sync/atomic"
    22  	"testing"
    23  	"time"
    24  
    25  	"github.com/fagongzi/goetty/v2"
    26  	"github.com/fagongzi/goetty/v2/codec"
    27  	"github.com/fagongzi/goetty/v2/codec/simple"
    28  	"github.com/smartystreets/goconvey/convey"
    29  
    30  	"github.com/matrixorigin/matrixone/pkg/common/moerr"
    31  	"github.com/matrixorigin/matrixone/pkg/logutil"
    32  )
    33  
    34  func TestBasicIOPackage_WriteUint8(t *testing.T) {
    35  	var buffer = make([]byte, 256)
    36  	var pos = 0
    37  	var IO IOPackageImpl
    38  	var prePos int
    39  	for i := 0; i < 256; i++ {
    40  		prePos = pos
    41  		pos = IO.WriteUint8(buffer, pos, uint8(i))
    42  		if pos != prePos+1 {
    43  			t.Errorf("WriteUint8 value %d failed.", i)
    44  			break
    45  		}
    46  		if buffer[i] != uint8(i) {
    47  			t.Errorf("WriteUint8 value %d failed.", i)
    48  			break
    49  		}
    50  	}
    51  }
    52  
    53  func TestBasicIOPackage_WriteUint16(t *testing.T) {
    54  	var buffer = make([]byte, 65536*2)
    55  	var pos = 0
    56  	var IO IOPackageImpl
    57  	var prePos int
    58  	for i := 0; i < 65536; i++ {
    59  		value := uint16(i)
    60  		prePos = pos
    61  		pos = IO.WriteUint16(buffer, pos, value)
    62  		if pos != prePos+2 {
    63  			t.Errorf("WriteUint16 value %d failed.", value)
    64  			break
    65  		}
    66  
    67  		var b1, b2 uint8
    68  		if IO.IsLittleEndian() {
    69  			b1 = uint8(value & 0xff)
    70  			b2 = uint8((value >> 8) & 0xff)
    71  		} else {
    72  			b1 = uint8((value >> 8) & 0xff)
    73  			b2 = uint8(value & 0xff)
    74  		}
    75  
    76  		p := 2 * i
    77  		if !(buffer[p] == b1 && buffer[p+1] == b2) {
    78  			t.Errorf("WriteUint16 value %d failed.", value)
    79  			break
    80  		}
    81  	}
    82  }
    83  
    84  func TestBasicIOPackage_WriteUint32(t *testing.T) {
    85  	var buffer = make([]byte, 65536*4)
    86  	var pos = 0
    87  	var IO IOPackageImpl
    88  	var prePos int
    89  	for i := 0; i < 65536; i++ {
    90  		value := uint32(0x01010101 + i)
    91  		prePos = pos
    92  		pos = IO.WriteUint32(buffer, pos, value)
    93  		if pos != prePos+4 {
    94  			t.Errorf("WriteUint32 value %d failed.", value)
    95  			break
    96  		}
    97  		var b1, b2, b3, b4 uint8
    98  		if IO.IsLittleEndian() {
    99  			b1 = uint8(value & 0xff)
   100  			b2 = uint8((value >> 8) & 0xff)
   101  			b3 = uint8((value >> 16) & 0xff)
   102  			b4 = uint8((value >> 24) & 0xff)
   103  		} else {
   104  			b4 = uint8(value & 0xff)
   105  			b3 = uint8((value >> 8) & 0xff)
   106  			b2 = uint8((value >> 16) & 0xff)
   107  			b1 = uint8((value >> 24) & 0xff)
   108  		}
   109  
   110  		p := 4 * i
   111  		if !(buffer[p] == b1 && buffer[p+1] == b2 && buffer[p+2] == b3 && buffer[p+3] == b4) {
   112  			t.Errorf("WriteUint32 value %d failed.", value)
   113  			break
   114  		}
   115  	}
   116  }
   117  
   118  func TestBasicIOPackage_WriteUint64(t *testing.T) {
   119  	var buffer = make([]byte, 65536*8)
   120  	var pos = 0
   121  	var IO IOPackageImpl
   122  	var prePos int
   123  	for i := 0; i < 65536; i++ {
   124  		value := uint64(0x0101010101010101 + i)
   125  		prePos = pos
   126  		pos = IO.WriteUint64(buffer, pos, value)
   127  		if pos != prePos+8 {
   128  			t.Errorf("WriteUint64 value %d failed.", value)
   129  			break
   130  		}
   131  		var b1, b2, b3, b4, b5, b6, b7, b8 uint8
   132  		if IO.IsLittleEndian() {
   133  			b1 = uint8(value & 0xff)
   134  			b2 = uint8((value >> 8) & 0xff)
   135  			b3 = uint8((value >> 16) & 0xff)
   136  			b4 = uint8((value >> 24) & 0xff)
   137  			b5 = uint8((value >> 32) & 0xff)
   138  			b6 = uint8((value >> 40) & 0xff)
   139  			b7 = uint8((value >> 48) & 0xff)
   140  			b8 = uint8((value >> 56) & 0xff)
   141  		} else {
   142  			b8 = uint8(value & 0xff)
   143  			b7 = uint8((value >> 8) & 0xff)
   144  			b6 = uint8((value >> 16) & 0xff)
   145  			b5 = uint8((value >> 24) & 0xff)
   146  			b4 = uint8((value >> 32) & 0xff)
   147  			b3 = uint8((value >> 40) & 0xff)
   148  			b2 = uint8((value >> 48) & 0xff)
   149  			b1 = uint8((value >> 56) & 0xff)
   150  		}
   151  
   152  		p := 8 * i
   153  		if !(buffer[p] == b1 && buffer[p+1] == b2 && buffer[p+2] == b3 && buffer[p+3] == b4 &&
   154  			buffer[p+4] == b5 && buffer[p+5] == b6 && buffer[p+6] == b7 && buffer[p+7] == b8) {
   155  			t.Errorf("WriteUint64 value %d failed.", value)
   156  			break
   157  		}
   158  	}
   159  }
   160  
   161  func TestBasicIOPackage_ReadUint8(t *testing.T) {
   162  	var buffer = make([]byte, 256)
   163  	var pos = 0
   164  	var IO IOPackageImpl
   165  	var prePos int
   166  	for i := 0; i < 256; i++ {
   167  		prePos = pos
   168  		IO.WriteUint8(buffer, pos, uint8(i))
   169  		rValue, pos, ok := IO.ReadUint8(buffer, pos)
   170  		if !ok || rValue != uint8(i) || pos != prePos+1 {
   171  			t.Errorf("ReadUint8 value %d failed.", i)
   172  			break
   173  		}
   174  	}
   175  }
   176  
   177  func TestBasicIOPackage_ReadUint16(t *testing.T) {
   178  	var buffer = make([]byte, 65536*2)
   179  	var pos = 0
   180  	var IO IOPackageImpl
   181  	var prePos int
   182  	for i := 0; i < 65536; i++ {
   183  		value := uint16(i)
   184  		prePos = pos
   185  		IO.WriteUint16(buffer, pos, value)
   186  		rValue, pos, ok := IO.ReadUint16(buffer, pos)
   187  		if !ok || pos != prePos+2 || rValue != value {
   188  			t.Errorf("ReadUint16 value %d failed.", value)
   189  			break
   190  		}
   191  	}
   192  }
   193  
   194  func TestBasicIOPackage_ReadUint32(t *testing.T) {
   195  	var buffer = make([]byte, 65536*4)
   196  	var pos = 0
   197  	var IO IOPackageImpl
   198  	var prePos int
   199  	for i := 0; i < 65536; i++ {
   200  		value := uint32(0x01010101 + i)
   201  		prePos = pos
   202  		IO.WriteUint32(buffer, pos, value)
   203  		rValue, pos, ok := IO.ReadUint32(buffer, pos)
   204  		if !ok || pos != prePos+4 || rValue != value {
   205  			t.Errorf("ReadUint32 value %d failed.", value)
   206  			break
   207  		}
   208  	}
   209  }
   210  
   211  func TestBasicIOPackage_ReadUint64(t *testing.T) {
   212  	var buffer = make([]byte, 65536*8)
   213  	var pos = 0
   214  	var IO IOPackageImpl
   215  	var prePos int
   216  	for i := 0; i < 65536; i++ {
   217  		value := uint64(0x0101010101010101 + i)
   218  		prePos = pos
   219  		IO.WriteUint64(buffer, pos, value)
   220  		rValue, pos, ok := IO.ReadUint64(buffer, pos)
   221  		if !ok || pos != prePos+8 || rValue != value {
   222  			t.Errorf("ReadUint64 value %d failed.", value)
   223  			break
   224  		}
   225  	}
   226  }
   227  
   228  var svrRun int32
   229  
   230  func isClosed() bool {
   231  	return atomic.LoadInt32(&svrRun) != 0
   232  }
   233  
   234  func setServer(val int32) {
   235  	atomic.StoreInt32(&svrRun, val)
   236  }
   237  
   238  func echoHandler(session goetty.IOSession, msg interface{}, received uint64) error {
   239  	value, ok := msg.(string)
   240  	if !ok {
   241  		return moerr.NewInternalError(context.TODO(), "convert to string failed")
   242  	}
   243  
   244  	err := session.Write(value, goetty.WriteOptions{Flush: true})
   245  	if err != nil {
   246  		return err
   247  	}
   248  	return nil
   249  }
   250  
   251  func echoServer(handler func(goetty.IOSession, interface{}, uint64) error, aware goetty.IOSessionAware,
   252  	codec codec.Codec) {
   253  	echoServer, err := goetty.NewApplication("127.0.0.1:6001", handler,
   254  		goetty.WithAppSessionOptions(
   255  			goetty.WithSessionCodec(codec),
   256  			goetty.WithSessionLogger(logutil.GetGlobalLogger())),
   257  		goetty.WithAppSessionAware(aware))
   258  	if err != nil {
   259  		panic(err)
   260  	}
   261  	err = echoServer.Start()
   262  	if err != nil {
   263  		panic(err)
   264  	}
   265  	setServer(0)
   266  
   267  	fmt.Println("Server started")
   268  	to := NewTimeout(5*time.Minute, false)
   269  	for !isClosed() && !to.isTimeout() {
   270  	}
   271  	err = echoServer.Stop()
   272  	if err != nil {
   273  		return
   274  	}
   275  	fmt.Println("Server exited")
   276  }
   277  
   278  func echoClient() {
   279  	addrPort := "localhost:6001"
   280  	io := goetty.NewIOSession(goetty.WithSessionCodec(simple.NewStringCodec()))
   281  	err := io.Connect(addrPort, time.Second*3)
   282  	if err != nil {
   283  		fmt.Println("connect server failed.", err.Error())
   284  		return
   285  	}
   286  
   287  	alphabet := [10]string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}
   288  
   289  	for i := 0; i < 10; i++ {
   290  		err := io.Write(alphabet[i], goetty.WriteOptions{Flush: true})
   291  		if err != nil {
   292  			fmt.Println("client writes packet failed.", err.Error())
   293  			break
   294  		}
   295  		fmt.Printf("client writes %s.\n", alphabet[i])
   296  		data, err := io.Read(goetty.ReadOptions{})
   297  		if err != nil {
   298  			fmt.Println("client reads packet failed.", err.Error())
   299  			break
   300  		}
   301  		value, ok := data.(string)
   302  		if !ok {
   303  			fmt.Println("convert to string failed.")
   304  			break
   305  		}
   306  		fmt.Printf("client reads %s.\n", value)
   307  		if value != alphabet[i] {
   308  			fmt.Printf("echo failed. send %s but response %s\n", alphabet[i], value)
   309  			break
   310  		}
   311  	}
   312  	err = io.Close()
   313  	if err != nil {
   314  		return
   315  	}
   316  }
   317  
   318  func TestIOPackageImpl_ReadPacket(t *testing.T) {
   319  	wg := sync.WaitGroup{}
   320  	wg.Add(1)
   321  	go func() {
   322  		defer wg.Done()
   323  		echoServer(echoHandler, nil, simple.NewStringCodec())
   324  	}()
   325  
   326  	to := NewTimeout(1*time.Minute, false)
   327  	for isClosed() && !to.isTimeout() {
   328  	}
   329  	time.Sleep(15 * time.Second)
   330  	echoClient()
   331  	setServer(1)
   332  	wg.Wait()
   333  }
   334  
   335  func Test_AppendUint(t *testing.T) {
   336  	convey.Convey("AppendUint succ", t, func() {
   337  		var io IOPackageImpl
   338  		var data, data2 = []byte{'a'}, []byte{'a', 'b'}
   339  		var value uint8 = 'b'
   340  		data = io.AppendUint8(data, value)
   341  		convey.So(data, convey.ShouldResemble, data2)
   342  
   343  		var value2 uint16 = 'c'
   344  		data = io.AppendUint16(data, value2)
   345  		data2 = append(data2, []byte{0, 'c'}...)
   346  		convey.So(data, convey.ShouldResemble, data2)
   347  
   348  		var value3 uint32 = 'd'
   349  		data = io.AppendUint32(data, value3)
   350  		data2 = append(data2, []byte{0, 0, 0, 'd'}...)
   351  		convey.So(data, convey.ShouldResemble, data2)
   352  
   353  		var value4 uint64 = 'e'
   354  		data = io.AppendUint64(data, value4)
   355  		data2 = append(data2, []byte{0, 0, 0, 0, 0, 0, 0, 'e'}...)
   356  		convey.So(data, convey.ShouldResemble, data2)
   357  
   358  		var pos = 9
   359  		u, i, b := io.ReadUint64(data, pos)
   360  		convey.So(u, convey.ShouldEqual, 0)
   361  		convey.So(i, convey.ShouldEqual, 0)
   362  		convey.So(b, convey.ShouldEqual, false)
   363  
   364  		io.endian = true
   365  		pos = 0
   366  		_, i, b = io.ReadUint64(data, pos)
   367  		convey.So(i, convey.ShouldEqual, 8)
   368  		convey.So(b, convey.ShouldEqual, true)
   369  	})
   370  }