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