mirror of
https://gitee.com/rulego/streamsql.git
synced 2026-03-09 12:04:27 +00:00
233 lines
5.5 KiB
Go
233 lines
5.5 KiB
Go
/*
|
|
* Copyright 2025 The RuleGo 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 types
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// TestRow 测试 Row 结构体的基本功能
|
|
func TestRow(t *testing.T) {
|
|
testTime := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
testData := map[string]interface{}{
|
|
"user_id": 123,
|
|
"amount": 99.99,
|
|
"status": "active",
|
|
}
|
|
testSlot := &TimeSlot{
|
|
Start: &testTime,
|
|
End: func() *time.Time { t := testTime.Add(time.Hour); return &t }(),
|
|
}
|
|
|
|
row := &Row{
|
|
Timestamp: testTime,
|
|
Data: testData,
|
|
Slot: testSlot,
|
|
}
|
|
|
|
// 测试 GetTimestamp 方法
|
|
if !row.GetTimestamp().Equal(testTime) {
|
|
t.Errorf("Expected timestamp %v, got %v", testTime, row.GetTimestamp())
|
|
}
|
|
|
|
// 测试 Timestamp 字段
|
|
if !row.Timestamp.Equal(testTime) {
|
|
t.Errorf("Expected timestamp %v, got %v", testTime, row.Timestamp)
|
|
}
|
|
|
|
// 测试 Data 字段
|
|
if row.Data == nil {
|
|
t.Error("Expected Data to be non-nil")
|
|
}
|
|
|
|
dataMap, ok := row.Data.(map[string]interface{})
|
|
if !ok {
|
|
t.Error("Expected Data to be a map[string]interface{}")
|
|
}
|
|
|
|
if dataMap["user_id"] != 123 {
|
|
t.Errorf("Expected user_id 123, got %v", dataMap["user_id"])
|
|
}
|
|
|
|
if dataMap["amount"] != 99.99 {
|
|
t.Errorf("Expected amount 99.99, got %v", dataMap["amount"])
|
|
}
|
|
|
|
if dataMap["status"] != "active" {
|
|
t.Errorf("Expected status 'active', got %v", dataMap["status"])
|
|
}
|
|
|
|
// 测试 Slot 字段
|
|
if row.Slot == nil {
|
|
t.Error("Expected Slot to be non-nil")
|
|
}
|
|
|
|
if !row.Slot.Start.Equal(testTime) {
|
|
t.Errorf("Expected slot start %v, got %v", testTime, row.Slot.Start)
|
|
}
|
|
|
|
if !row.Slot.End.Equal(testTime.Add(time.Hour)) {
|
|
t.Errorf("Expected slot end %v, got %v", testTime.Add(time.Hour), row.Slot.End)
|
|
}
|
|
}
|
|
|
|
// TestRowWithNilData 测试 Row 结构体处理 nil 数据的情况
|
|
func TestRowWithNilData(t *testing.T) {
|
|
testTime := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
|
|
row := &Row{
|
|
Timestamp: testTime,
|
|
Data: nil,
|
|
Slot: nil,
|
|
}
|
|
|
|
// 测试 GetTimestamp 方法仍然正常工作
|
|
if !row.GetTimestamp().Equal(testTime) {
|
|
t.Errorf("Expected timestamp %v, got %v", testTime, row.GetTimestamp())
|
|
}
|
|
|
|
// 测试 nil 数据
|
|
if row.Data != nil {
|
|
t.Error("Expected Data to be nil")
|
|
}
|
|
|
|
// 测试 nil slot
|
|
if row.Slot != nil {
|
|
t.Error("Expected Slot to be nil")
|
|
}
|
|
}
|
|
|
|
// TestRowWithDifferentDataTypes 测试 Row 结构体处理不同数据类型的情况
|
|
func TestRowWithDifferentDataTypes(t *testing.T) {
|
|
testTime := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
|
|
// 测试字符串数据
|
|
rowString := &Row{
|
|
Timestamp: testTime,
|
|
Data: "test string data",
|
|
}
|
|
|
|
if rowString.Data != "test string data" {
|
|
t.Errorf("Expected string data 'test string data', got %v", rowString.Data)
|
|
}
|
|
|
|
// 测试数字数据
|
|
rowNumber := &Row{
|
|
Timestamp: testTime,
|
|
Data: 42,
|
|
}
|
|
|
|
if rowNumber.Data != 42 {
|
|
t.Errorf("Expected number data 42, got %v", rowNumber.Data)
|
|
}
|
|
|
|
// 测试布尔数据
|
|
rowBool := &Row{
|
|
Timestamp: testTime,
|
|
Data: true,
|
|
}
|
|
|
|
if rowBool.Data != true {
|
|
t.Errorf("Expected boolean data true, got %v", rowBool.Data)
|
|
}
|
|
|
|
// 测试切片数据
|
|
sliceData := []string{"item1", "item2", "item3"}
|
|
rowSlice := &Row{
|
|
Timestamp: testTime,
|
|
Data: sliceData,
|
|
}
|
|
|
|
resultSlice, ok := rowSlice.Data.([]string)
|
|
if !ok {
|
|
t.Error("Expected Data to be a []string")
|
|
}
|
|
|
|
if len(resultSlice) != 3 {
|
|
t.Errorf("Expected slice length 3, got %d", len(resultSlice))
|
|
}
|
|
|
|
if resultSlice[0] != "item1" {
|
|
t.Errorf("Expected first item 'item1', got %v", resultSlice[0])
|
|
}
|
|
}
|
|
|
|
// TestRowEventInterface 测试 Row 实现 RowEvent 接口
|
|
func TestRowEventInterface(t *testing.T) {
|
|
testTime := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
|
|
row := &Row{
|
|
Timestamp: testTime,
|
|
Data: "test data",
|
|
}
|
|
|
|
// 验证 Row 实现了 RowEvent 接口
|
|
var rowEvent RowEvent = row
|
|
|
|
if !rowEvent.GetTimestamp().Equal(testTime) {
|
|
t.Errorf("Expected timestamp %v from RowEvent interface, got %v", testTime, rowEvent.GetTimestamp())
|
|
}
|
|
}
|
|
|
|
// TestRowZeroTime 测试 Row 结构体处理零时间的情况
|
|
func TestRowZeroTime(t *testing.T) {
|
|
zeroTime := time.Time{}
|
|
|
|
row := &Row{
|
|
Timestamp: zeroTime,
|
|
Data: "test data",
|
|
}
|
|
|
|
if !row.GetTimestamp().Equal(zeroTime) {
|
|
t.Errorf("Expected zero timestamp %v, got %v", zeroTime, row.GetTimestamp())
|
|
}
|
|
|
|
if !row.GetTimestamp().IsZero() {
|
|
t.Error("Expected timestamp to be zero")
|
|
}
|
|
}
|
|
|
|
// TestRowConcurrentAccess 测试 Row 结构体的并发访问
|
|
func TestRowConcurrentAccess(t *testing.T) {
|
|
testTime := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
|
|
row := &Row{
|
|
Timestamp: testTime,
|
|
Data: "test data",
|
|
}
|
|
|
|
// 启动多个 goroutine 并发访问 GetTimestamp 方法
|
|
done := make(chan bool, 10)
|
|
for i := 0; i < 10; i++ {
|
|
go func() {
|
|
for j := 0; j < 100; j++ {
|
|
timestamp := row.GetTimestamp()
|
|
if !timestamp.Equal(testTime) {
|
|
t.Errorf("Concurrent access failed: expected %v, got %v", testTime, timestamp)
|
|
}
|
|
}
|
|
done <- true
|
|
}()
|
|
}
|
|
|
|
// 等待所有 goroutine 完成
|
|
for i := 0; i < 10; i++ {
|
|
<-done
|
|
}
|
|
}
|