소스 검색

test(pkg): add unit tests (#1899)

* test(pkg): add unit tests

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* test: add ut for stream.go

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* test: add method tests

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* test: add errors test

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* test: add infra tests

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* chore: rename to tt

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* test: add cast/time tests

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* test: add test case infra

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* chore: complete comment

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

* test: cast tests

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>

---------

Signed-off-by: xjasonlyu <xjasonlyu@gmail.com>
Jason Lyu 1 년 전
부모
커밋
5ed7173ee8
8개의 변경된 파일737개의 추가작업 그리고 76개의 파일을 삭제
  1. 3 0
      go.mod
  2. 48 0
      pkg/api/stream_test.go
  3. 1 1
      pkg/ast/expr.go
  4. 377 17
      pkg/cast/cast_test.go
  5. 158 58
      pkg/cast/time_test.go
  6. 40 0
      pkg/errorx/errors_test.go
  7. 73 0
      pkg/infra/saferun_test.go
  8. 37 0
      pkg/message/artifacts_test.go

+ 3 - 0
go.mod

@@ -31,6 +31,7 @@ require (
 	github.com/robfig/cron/v3 v3.0.0
 	github.com/second-state/WasmEdge-go v0.12.0-alpha.2
 	github.com/sirupsen/logrus v1.9.0
+	github.com/stretchr/testify v1.8.2
 	github.com/ugorji/go/codec v1.2.10
 	github.com/urfave/cli v1.22.12
 	go.nanomsg.org/mangos/v3 v3.4.2
@@ -52,6 +53,7 @@ require (
 	github.com/bufbuild/protocompile v0.3.0 // indirect
 	github.com/cespare/xxhash/v2 v2.2.0 // indirect
 	github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
+	github.com/davecgh/go-spew v1.1.1 // indirect
 	github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
 	github.com/dlclark/regexp2 v1.8.1 // indirect
 	github.com/dustin/go-humanize v1.0.0 // indirect
@@ -82,6 +84,7 @@ require (
 	github.com/nats-io/nkeys v0.3.0 // indirect
 	github.com/nats-io/nuid v1.0.1 // indirect
 	github.com/pkg/errors v0.9.1 // indirect
+	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/prometheus/client_model v0.3.0 // indirect
 	github.com/prometheus/common v0.40.0 // indirect
 	github.com/prometheus/procfs v0.9.0 // indirect

+ 48 - 0
pkg/api/stream_test.go

@@ -0,0 +1,48 @@
+// Copyright 2023 EMQ Technologies Co., Ltd.
+//
+// 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 api
+
+import (
+	"testing"
+	"time"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestDefaultSourceTupleResult(t *testing.T) {
+	now := time.Now()
+
+	st := NewDefaultSourceTupleWithTime(nil, nil, now)
+
+	assert.Equal(t, &DefaultSourceTuple{
+		Mess: nil,
+		M:    nil,
+		Time: now,
+	}, st)
+	assert.Nil(t, st.Message())
+	assert.Nil(t, st.Meta())
+	assert.Equal(t, now, st.Timestamp())
+
+	st = NewDefaultSourceTuple(nil, nil)
+
+	assert.Equal(t, &DefaultSourceTuple{
+		Mess: nil,
+		M:    nil,
+		Time: st.Time,
+	}, st)
+	assert.Nil(t, st.Message())
+	assert.Nil(t, st.Meta())
+	assert.NotEqual(t, now, st.Timestamp())
+}

+ 1 - 1
pkg/ast/expr.go

@@ -317,7 +317,7 @@ func NewAliasRef(e Expr) (*AliasRef, error) {
 	}, nil
 }
 
-// for testing only
+// MockAliasRef is for testing only.
 func MockAliasRef(e Expr, r []StreamName, a *bool) *AliasRef {
 	return &AliasRef{e, r, a}
 }

+ 377 - 17
pkg/cast/cast_test.go

@@ -1,4 +1,4 @@
-// Copyright 2021-2022 EMQ Technologies Co., Ltd.
+// Copyright 2021-2023 EMQ Technologies Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -16,12 +16,377 @@ package cast
 
 import (
 	"encoding/hex"
+	"errors"
 	"fmt"
+	"net"
 	"reflect"
 	"testing"
+
+	"github.com/stretchr/testify/assert"
 )
 
-func TestMapConvert_Funcs(t *testing.T) {
+func TestToStringAlways(t *testing.T) {
+	tests := []struct {
+		input any
+		want  string
+	}{
+		{
+			"test",
+			"test",
+		},
+		{
+			100,
+			"100",
+		},
+		{
+			nil,
+			"",
+		},
+	}
+	for _, tt := range tests {
+		assert.Equal(t, tt.want, ToStringAlways(tt.input))
+	}
+}
+
+func TestToString(t *testing.T) {
+	tests := []struct {
+		input any
+		sn    Strictness
+		want  string
+	}{
+		{
+			"test",
+			CONVERT_SAMEKIND,
+			"test",
+		},
+		{
+			[]byte("test"),
+			CONVERT_SAMEKIND,
+			"test",
+		},
+		{
+			true,
+			CONVERT_ALL,
+			"true",
+		},
+		{
+			nil,
+			CONVERT_ALL,
+			"",
+		},
+		{
+			100,
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			int8(100),
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			int16(100),
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			int32(100),
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			int64(100),
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			uint(100),
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			uint8(100),
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			uint16(100),
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			uint32(100),
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			uint64(100),
+			CONVERT_ALL,
+			"100",
+		},
+		{
+			float32(100.001),
+			CONVERT_ALL,
+			"100.001",
+		},
+		{
+			100.001,
+			CONVERT_ALL,
+			"100.001",
+		},
+		{
+			// Stringer test case
+			net.IPv4(0, 0, 0, 0),
+			CONVERT_ALL,
+			"0.0.0.0",
+		},
+		{
+			errors.New("test"),
+			CONVERT_ALL,
+			"test",
+		},
+	}
+	for _, tt := range tests {
+		got, err := ToString(tt.input, tt.sn)
+		assert.NoError(t, err)
+		assert.Equal(t, tt.want, got)
+	}
+
+	_, err := ToString(struct{}{}, STRICT)
+	assert.Error(t, err)
+}
+
+func TestToIntResult(t *testing.T) {
+	tests := []struct {
+		input any
+		want  int64
+	}{
+		{
+			100,
+			100,
+		},
+		{
+			int8(100),
+			100,
+		},
+		{
+			int16(100),
+			100,
+		},
+		{
+			int32(100),
+			100,
+		},
+		{
+			int64(100),
+			100,
+		},
+		{
+			uint(100),
+			100,
+		},
+		{
+			uint8(100),
+			100,
+		},
+		{
+			uint16(100),
+			100,
+		},
+		{
+			uint32(100),
+			100,
+		},
+		{
+			uint64(100),
+			100,
+		},
+		{
+			float32(100),
+			100,
+		},
+		{
+			float64(100),
+			100,
+		},
+		{
+			"100",
+			100,
+		},
+		{
+			false,
+			0,
+		},
+		{
+			nil,
+			0,
+		},
+	}
+	for _, tt := range tests {
+		var (
+			got any
+			err error
+		)
+		got, err = ToInt(tt.input, CONVERT_ALL)
+		assert.NoError(t, err)
+		assert.Equal(t, int(tt.want), got)
+
+		got, err = ToInt8(tt.input, CONVERT_ALL)
+		assert.NoError(t, err)
+		assert.Equal(t, int8(tt.want), got)
+
+		got, err = ToInt16(tt.input, CONVERT_ALL)
+		assert.NoError(t, err)
+		assert.Equal(t, int16(tt.want), got)
+
+		got, err = ToInt32(tt.input, CONVERT_ALL)
+		assert.NoError(t, err)
+		assert.Equal(t, int32(tt.want), got)
+
+		got, err = ToInt64(tt.input, CONVERT_ALL)
+		assert.NoError(t, err)
+		assert.Equal(t, tt.want, got)
+	}
+
+	errTests := []any{
+		true,
+		nil,
+		"1",
+	}
+	for _, input := range errTests {
+		_, err := ToInt(input, STRICT)
+		assert.Error(t, err)
+
+		_, err = ToInt8(input, STRICT)
+		assert.Error(t, err)
+
+		_, err = ToInt16(input, STRICT)
+		assert.Error(t, err)
+
+		_, err = ToInt32(input, STRICT)
+		assert.Error(t, err)
+
+		_, err = ToInt64(input, STRICT)
+		assert.Error(t, err)
+	}
+}
+
+func TestToUintResult(t *testing.T) {
+	tests := []struct {
+		input any
+		want  uint64
+	}{
+		{
+			100,
+			100,
+		},
+		{
+			int8(100),
+			100,
+		},
+		{
+			int16(100),
+			100,
+		},
+		{
+			int32(100),
+			100,
+		},
+		{
+			int64(100),
+			100,
+		},
+		{
+			uint(100),
+			100,
+		},
+		{
+			uint8(100),
+			100,
+		},
+		{
+			uint16(100),
+			100,
+		},
+		{
+			uint32(100),
+			100,
+		},
+		{
+			uint64(100),
+			100,
+		},
+		{
+			float32(100),
+			100,
+		},
+		{
+			float64(100),
+			100,
+		},
+		{
+			"100",
+			100,
+		},
+		{
+			false,
+			0,
+		},
+		{
+			nil,
+			0,
+		},
+	}
+	for _, tt := range tests {
+		var (
+			got any
+			err error
+		)
+		got, err = ToUint8(tt.input, CONVERT_ALL)
+		assert.NoError(t, err)
+		assert.Equal(t, uint8(tt.want), got)
+
+		got, err = ToUint16(tt.input, CONVERT_ALL)
+		assert.NoError(t, err)
+		assert.Equal(t, uint16(tt.want), got)
+
+		got, err = ToUint32(tt.input, CONVERT_ALL)
+		assert.NoError(t, err)
+		assert.Equal(t, uint32(tt.want), got)
+
+		got, err = ToUint64(tt.input, CONVERT_ALL)
+		assert.NoError(t, err)
+		assert.Equal(t, tt.want, got)
+	}
+
+	errTests := []any{
+		-1,
+		int8(-1),
+		int16(-1),
+		int32(-1),
+		int64(-1),
+		float32(-1),
+		float64(-1),
+		true,
+		nil,
+		"1",
+	}
+	for _, input := range errTests {
+		_, err := ToUint8(input, STRICT)
+		assert.Error(t, err)
+
+		_, err = ToUint16(input, STRICT)
+		assert.Error(t, err)
+
+		_, err = ToUint32(input, STRICT)
+		assert.Error(t, err)
+
+		_, err = ToUint64(input, STRICT)
+		assert.Error(t, err)
+	}
+}
+
+func TestMapConvert(t *testing.T) {
 	source := map[interface{}]interface{}{
 		"QUERY_TABLE": "VBAP",
 		"ROWCOUNT":    10,
@@ -32,7 +397,7 @@ func TestMapConvert_Funcs(t *testing.T) {
 		},
 	}
 
-	exp := map[string]interface{}{
+	assert.Equal(t, map[string]interface{}{
 		"QUERY_TABLE": "VBAP",
 		"ROWCOUNT":    10,
 		"FIELDS": []interface{}{
@@ -40,12 +405,7 @@ func TestMapConvert_Funcs(t *testing.T) {
 			map[string]interface{}{"FIELDNAME": "VBELN"},
 			map[string]interface{}{"FIELDNAME": "POSNR"},
 		},
-	}
-
-	got := ConvertMap(source)
-	if !reflect.DeepEqual(exp, got) {
-		t.Errorf("result mismatch:\n\nexp=%s\n\ngot=%s\n\n", exp, got)
-	}
+	}, ConvertMap(source))
 }
 
 func TestToTypedSlice(t *testing.T) {
@@ -77,7 +437,14 @@ func TestToTypedSlice(t *testing.T) {
 			}
 		}, "string", CONVERT_SAMEKIND)
 
-		if !reflect.DeepEqual(tt.e, errstring(err)) {
+		errString := func(err error) string {
+			if err != nil {
+				return err.Error()
+			}
+			return ""
+		}
+
+		if !reflect.DeepEqual(tt.e, errString(err)) {
 			t.Errorf("%d: error mismatch:\n  exp=%s\n  got=%s\n\n", i, tt.e, err)
 		} else if tt.e == "" && !reflect.DeepEqual(tt.r, result) {
 			t.Errorf("%d\n\nstmt mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.r, result)
@@ -85,13 +452,6 @@ func TestToTypedSlice(t *testing.T) {
 	}
 }
 
-func errstring(err error) string {
-	if err != nil {
-		return err.Error()
-	}
-	return ""
-}
-
 func TestMapToStructStrict(t *testing.T) {
 	type args struct {
 		input  interface{}

+ 158 - 58
pkg/cast/time_test.go

@@ -1,4 +1,4 @@
-// Copyright 2022 EMQ Technologies Co., Ltd.
+// Copyright 2022-2023 EMQ Technologies Co., Ltd.
 //
 // Licensed under the Apache License, Version 2.0 (the "License");
 // you may not use this file except in compliance with the License.
@@ -15,12 +15,13 @@
 package cast
 
 import (
-	"reflect"
 	"testing"
 	"time"
+
+	"github.com/stretchr/testify/assert"
 )
 
-func TestDateToAndFromMilli(t *testing.T) {
+func TestTimeToAndFromMilli(t *testing.T) {
 	tests := []struct {
 		m int64
 		t time.Time
@@ -32,91 +33,190 @@ func TestDateToAndFromMilli(t *testing.T) {
 	}
 	for i, tt := range tests {
 		time := TimeFromUnixMilli(tt.m)
-		if !time.Equal(tt.t) {
-			t.Errorf("%d time from milli result mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.t, time)
-		}
+		assert.Equal(t, tt.t, time, "%d time from milli result mismatch:\n\nexp=%#v\n\ngot=%#v", i, tt.t, time)
+
 		milli := TimeToUnixMilli(tt.t)
-		if tt.m != milli {
-			t.Errorf("%d time to milli result mismatch:\n\nexp=%#v\n\ngot=%#v\n\n", i, tt.m, milli)
-		}
+		assert.Equal(t, tt.m, milli, "%d time to milli result mismatch:\n\nexp=%#v\n\ngot=%#v", i, tt.m, milli)
 	}
 }
 
 func TestFormatTime(t *testing.T) {
-	type args struct {
-		time time.Time
-		f    string
-	}
+	date := time.Date(2020, time.January, 16, 2, 14, 24, 913000000, time.UTC)
 	tests := []struct {
-		name    string
-		args    args
+		format  string
 		want    string
 		wantErr bool
 	}{
 		{
-			name: "test1",
-			args: args{
-				time: time.Date(2020, time.January, 16, 2, 14, 24, 913000000, time.UTC),
-				f:    "YYYY-MM-dd HH:mm:ssSSS",
-			},
+			format:  "YYYY-MM-dd HH:mm:ssSSS",
 			want:    "2020-01-16 02:14:24.913",
 			wantErr: false,
 		},
 		{
-			name: "test1",
-			args: args{
-				time: time.Date(2020, time.January, 16, 2, 14, 24, 913000000, time.UTC),
-				f:    "YYYY-MM-dd T HH:mm:ss",
-			},
+			format:  "YYYY-MM-dd T HH:mm:ss",
 			want:    "2020-01-16 T 02:14:24",
 			wantErr: false,
 		},
+		{
+			format:  "YYY",
+			want:    "2020",
+			wantErr: true,
+		},
 	}
 	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			got, err := FormatTime(tt.args.time, tt.args.f)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("FormatTime() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if got != tt.want {
-				t.Errorf("FormatTime() got = %v, want %v", got, tt.want)
-			}
-		})
+		got, err := FormatTime(date, tt.format)
+		if tt.wantErr {
+			assert.Error(t, err)
+			continue
+		}
+		assert.NoError(t, err)
+		assert.Equal(t, tt.want, got)
 	}
 }
 
-func TestInterfaceToTime(t *testing.T) {
-	type args struct {
-		i      interface{}
-		format string
+func TestParseTime(t *testing.T) {
+	tests := []struct {
+		d       time.Time
+		t       string
+		f       string
+		wantErr bool
+	}{
+		{
+			time.Date(2020, time.January, 16, 2, 14, 24, 913000000, time.UTC),
+			"2020-01-16 02:14:24.913",
+			"YYYY-MM-dd HH:mm:ssSSS",
+			false,
+		},
+		{
+			time.Date(2020, time.January, 16, 2, 14, 24, 0, time.UTC),
+			"2020-01-16 02:14:24",
+			"YYYY-MM-dd HH:mm:ss",
+			false,
+		},
+		{
+			time.Time{},
+			"2020",
+			"YYY",
+			true,
+		},
 	}
+	for _, tt := range tests {
+		date, err := ParseTime(tt.t, tt.f)
+		if tt.wantErr {
+			assert.Error(t, err)
+			continue
+		}
+		assert.NoError(t, err)
+		assert.Equal(t, tt.d, date)
+	}
+}
+
+func TestInterfaceToTime(t *testing.T) {
 	tests := []struct {
-		name    string
-		args    args
+		i       interface{}
+		f       string
 		want    time.Time
 		wantErr bool
 	}{
 		{
-			name: "test string",
-			args: args{
-				i:      "2022-04-13 06:22:32.233",
-				format: "YYYY-MM-dd HH:mm:ssSSS",
-			},
-			want:    time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
-			wantErr: false,
+			"2022-04-13 06:22:32.233",
+			"YYYY-MM-dd HH:mm:ssSSS",
+			time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
+			false,
+		},
+		{
+			1649830952233,
+			"YYYY-MM-dd HH:mm:ssSSS",
+			time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
+			false,
+		},
+		{
+			int64(1649830952233),
+			"YYYY-MM-dd HH:mm:ssSSS",
+			time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
+			false,
+		},
+		{
+			float64(1649830952233),
+			"YYYY-MM-dd HH:mm:ssSSS",
+			time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
+			false,
+		},
+		{
+			time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
+			"YYYY-MM-dd HH:mm:ssSSS",
+			time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
+			false,
+		},
+		{
+			struct{}{},
+			"YYYY-MM-dd HH:mm:ssSSS",
+			time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
+			true,
+		},
+	}
+	for _, tt := range tests {
+		got, err := InterfaceToTime(tt.i, tt.f)
+		if tt.wantErr {
+			assert.Error(t, err)
+			continue
+		}
+		assert.NoError(t, err)
+		assert.Equal(t, tt.want, got)
+	}
+}
+
+func TestInterfaceToUnixMilli(t *testing.T) {
+	tests := []struct {
+		i       interface{}
+		f       string
+		want    int64
+		wantErr bool
+	}{
+		{
+			"2022-04-13 06:22:32.233",
+			"YYYY-MM-dd HH:mm:ssSSS",
+			1649830952233,
+			false,
+		},
+		{
+			1649830952233,
+			"YYYY-MM-dd HH:mm:ssSSS",
+			1649830952233,
+			false,
+		},
+		{
+			int64(1649830952233),
+			"YYYY-MM-dd HH:mm:ssSSS",
+			1649830952233,
+			false,
+		},
+		{
+			float64(1649830952233),
+			"YYYY-MM-dd HH:mm:ssSSS",
+			1649830952233,
+			false,
+		},
+		{
+			time.Date(2022, time.April, 13, 6, 22, 32, 233000000, time.UTC),
+			"YYYY-MM-dd HH:mm:ssSSS",
+			1649830952233,
+			false,
+		},
+		{
+			struct{}{},
+			"YYYY-MM-dd HH:mm:ssSSS",
+			1649830952233,
+			true,
 		},
 	}
 	for _, tt := range tests {
-		t.Run(tt.name, func(t *testing.T) {
-			got, err := InterfaceToTime(tt.args.i, tt.args.format)
-			if (err != nil) != tt.wantErr {
-				t.Errorf("InterfaceToTime() error = %v, wantErr %v", err, tt.wantErr)
-				return
-			}
-			if !reflect.DeepEqual(got, tt.want) {
-				t.Errorf("InterfaceToTime() got = %v, want %v", got, tt.want)
-			}
-		})
+		got, err := InterfaceToUnixMilli(tt.i, tt.f)
+		if tt.wantErr {
+			assert.Error(t, err)
+			continue
+		}
+		assert.NoError(t, err)
+		assert.Equal(t, tt.want, got)
 	}
 }

+ 40 - 0
pkg/errorx/errors_test.go

@@ -0,0 +1,40 @@
+// Copyright 2023 EMQ Technologies Co., Ltd.
+//
+// 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 errorx
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestErrorResult(t *testing.T) {
+	err := New("general error")
+
+	assert.Equal(t, &Error{
+		"general error",
+		GENERAL_ERR,
+	}, err)
+	assert.Equal(t, "general error", err.Error())
+	assert.Equal(t, GENERAL_ERR, err.Code())
+
+	err = NewWithCode(NOT_FOUND, "not found")
+	assert.Equal(t, &Error{
+		"not found",
+		NOT_FOUND,
+	}, err)
+	assert.Equal(t, "not found", err.Error())
+	assert.Equal(t, NOT_FOUND, err.Code())
+}

+ 73 - 0
pkg/infra/saferun_test.go

@@ -0,0 +1,73 @@
+// Copyright 2023 EMQ Technologies Co., Ltd.
+//
+// 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 infra
+
+import (
+	"errors"
+	"fmt"
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestDrainError(t *testing.T) {
+	errChan := make(chan error, 1)
+	err := errors.New("test error")
+
+	go DrainError(nil, err, errChan)
+
+	assert.Equal(t, err, <-errChan)
+}
+
+func TestSafeRun(t *testing.T) {
+	tests := []struct {
+		fn       func() error
+		expected error
+	}{
+		{
+			func() error {
+				return nil
+			},
+			nil,
+		},
+		{
+			func() error {
+				return errors.New("test error")
+			},
+			errors.New("test error"),
+		},
+		{
+			func() error {
+				panic(errors.New("test error"))
+			},
+			errors.New("test error"),
+		},
+		{
+			func() error {
+				panic("panic error")
+			},
+			errors.New("panic error"),
+		},
+		{
+			func() error {
+				panic(2)
+			},
+			fmt.Errorf("%#v", 2),
+		},
+	}
+	for _, tt := range tests {
+		assert.Equal(t, tt.expected, SafeRun(tt.fn))
+	}
+}

+ 37 - 0
pkg/message/artifacts_test.go

@@ -0,0 +1,37 @@
+// Copyright 2023 EMQ Technologies Co., Ltd.
+//
+// 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 message
+
+import (
+	"testing"
+
+	"github.com/stretchr/testify/assert"
+)
+
+func TestIsFormatSupported(t *testing.T) {
+	formats := []string{
+		FormatBinary, FormatJson, FormatProtobuf, FormatDelimited, FormatCustom,
+	}
+	for _, format := range formats {
+		assert.True(t, IsFormatSupported(format))
+	}
+
+	badFormats := []string{
+		"BINARY", "Json", "DIY",
+	}
+	for _, format := range badFormats {
+		assert.False(t, IsFormatSupported(format))
+	}
+}