forked from GiteaTest2015/streamsql
308 lines
8.2 KiB
Go
308 lines
8.2 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"
|
|
)
|
|
|
|
// TestNewTimeSlot 测试 NewTimeSlot 构造函数
|
|
func TestNewTimeSlot(t *testing.T) {
|
|
start := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
end := time.Date(2024, 1, 1, 13, 0, 0, 0, time.UTC)
|
|
|
|
ts := NewTimeSlot(&start, &end)
|
|
|
|
if ts == nil {
|
|
t.Error("Expected TimeSlot to be non-nil")
|
|
}
|
|
|
|
if ts.Start == nil {
|
|
t.Error("Expected Start to be non-nil")
|
|
}
|
|
|
|
if ts.End == nil {
|
|
t.Error("Expected End to be non-nil")
|
|
}
|
|
|
|
if !ts.Start.Equal(start) {
|
|
t.Errorf("Expected start time %v, got %v", start, *ts.Start)
|
|
}
|
|
|
|
if !ts.End.Equal(end) {
|
|
t.Errorf("Expected end time %v, got %v", end, *ts.End)
|
|
}
|
|
}
|
|
|
|
// TestNewTimeSlotWithNil 测试 NewTimeSlot 处理 nil 参数的情况
|
|
func TestNewTimeSlotWithNil(t *testing.T) {
|
|
start := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
|
|
// 测试 end 为 nil
|
|
ts1 := NewTimeSlot(&start, nil)
|
|
if ts1.Start == nil {
|
|
t.Error("Expected Start to be non-nil")
|
|
}
|
|
if ts1.End != nil {
|
|
t.Error("Expected End to be nil")
|
|
}
|
|
|
|
// 测试 start 为 nil
|
|
ts2 := NewTimeSlot(nil, &start)
|
|
if ts2.Start != nil {
|
|
t.Error("Expected Start to be nil")
|
|
}
|
|
if ts2.End == nil {
|
|
t.Error("Expected End to be non-nil")
|
|
}
|
|
|
|
// 测试两者都为 nil
|
|
ts3 := NewTimeSlot(nil, nil)
|
|
if ts3.Start != nil {
|
|
t.Error("Expected Start to be nil")
|
|
}
|
|
if ts3.End != nil {
|
|
t.Error("Expected End to be nil")
|
|
}
|
|
}
|
|
|
|
// TestTimeSlotHash 测试 Hash 方法
|
|
func TestTimeSlotHash(t *testing.T) {
|
|
start := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
end := time.Date(2024, 1, 1, 13, 0, 0, 0, time.UTC)
|
|
|
|
ts1 := NewTimeSlot(&start, &end)
|
|
ts2 := NewTimeSlot(&start, &end)
|
|
|
|
hash1 := ts1.Hash()
|
|
hash2 := ts2.Hash()
|
|
|
|
// 相同的时间槽应该产生相同的哈希值
|
|
if hash1 != hash2 {
|
|
t.Errorf("Expected same hash for identical time slots, got %d and %d", hash1, hash2)
|
|
}
|
|
|
|
// 不同的时间槽应该产生不同的哈希值
|
|
differentEnd := time.Date(2024, 1, 1, 14, 0, 0, 0, time.UTC)
|
|
ts3 := NewTimeSlot(&start, &differentEnd)
|
|
hash3 := ts3.Hash()
|
|
|
|
if hash1 == hash3 {
|
|
t.Errorf("Expected different hash for different time slots, got same hash %d", hash1)
|
|
}
|
|
}
|
|
|
|
// TestTimeSlotContains 测试 Contains 方法
|
|
func TestTimeSlotContains(t *testing.T) {
|
|
start := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
end := time.Date(2024, 1, 1, 13, 0, 0, 0, time.UTC)
|
|
ts := NewTimeSlot(&start, &end)
|
|
|
|
// 测试边界情况
|
|
if !ts.Contains(start) {
|
|
t.Error("Expected Contains to return true for start time")
|
|
}
|
|
|
|
if ts.Contains(end) {
|
|
t.Error("Expected Contains to return false for end time (exclusive)")
|
|
}
|
|
|
|
// 测试范围内的时间
|
|
midTime := time.Date(2024, 1, 1, 12, 30, 0, 0, time.UTC)
|
|
if !ts.Contains(midTime) {
|
|
t.Error("Expected Contains to return true for time within range")
|
|
}
|
|
|
|
// 测试范围外的时间
|
|
beforeStart := time.Date(2024, 1, 1, 11, 59, 59, 0, time.UTC)
|
|
if ts.Contains(beforeStart) {
|
|
t.Error("Expected Contains to return false for time before start")
|
|
}
|
|
|
|
afterEnd := time.Date(2024, 1, 1, 13, 0, 1, 0, time.UTC)
|
|
if ts.Contains(afterEnd) {
|
|
t.Error("Expected Contains to return false for time after end")
|
|
}
|
|
}
|
|
|
|
// TestGetStartTime 测试 GetStartTime 方法
|
|
func TestGetStartTime(t *testing.T) {
|
|
start := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
end := time.Date(2024, 1, 1, 13, 0, 0, 0, time.UTC)
|
|
ts := NewTimeSlot(&start, &end)
|
|
|
|
startTime := ts.GetStartTime()
|
|
if startTime == nil {
|
|
t.Error("Expected GetStartTime to return non-nil")
|
|
}
|
|
|
|
if !startTime.Equal(start) {
|
|
t.Errorf("Expected start time %v, got %v", start, *startTime)
|
|
}
|
|
|
|
// 测试 nil TimeSlot
|
|
var nilTS *TimeSlot
|
|
nilStartTime := nilTS.GetStartTime()
|
|
if nilStartTime != nil {
|
|
t.Error("Expected GetStartTime to return nil for nil TimeSlot")
|
|
}
|
|
|
|
// 测试 Start 为 nil 的情况
|
|
tsWithNilStart := NewTimeSlot(nil, &end)
|
|
nilStart := tsWithNilStart.GetStartTime()
|
|
if nilStart != nil {
|
|
t.Error("Expected GetStartTime to return nil when Start is nil")
|
|
}
|
|
}
|
|
|
|
// TestGetEndTime 测试 GetEndTime 方法
|
|
func TestGetEndTime(t *testing.T) {
|
|
start := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
end := time.Date(2024, 1, 1, 13, 0, 0, 0, time.UTC)
|
|
ts := NewTimeSlot(&start, &end)
|
|
|
|
endTime := ts.GetEndTime()
|
|
if endTime == nil {
|
|
t.Error("Expected GetEndTime to return non-nil")
|
|
}
|
|
|
|
if !endTime.Equal(end) {
|
|
t.Errorf("Expected end time %v, got %v", end, *endTime)
|
|
}
|
|
|
|
// 测试 nil TimeSlot
|
|
var nilTS *TimeSlot
|
|
nilEndTime := nilTS.GetEndTime()
|
|
if nilEndTime != nil {
|
|
t.Error("Expected GetEndTime to return nil for nil TimeSlot")
|
|
}
|
|
|
|
// 测试 End 为 nil 的情况
|
|
tsWithNilEnd := NewTimeSlot(&start, nil)
|
|
nilEnd := tsWithNilEnd.GetEndTime()
|
|
if nilEnd != nil {
|
|
t.Error("Expected GetEndTime to return nil when End is nil")
|
|
}
|
|
}
|
|
|
|
// TestWindowStart 测试 WindowStart 方法
|
|
func TestWindowStart(t *testing.T) {
|
|
start := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
end := time.Date(2024, 1, 1, 13, 0, 0, 0, time.UTC)
|
|
ts := NewTimeSlot(&start, &end)
|
|
|
|
windowStart := ts.WindowStart()
|
|
expectedStart := start.UnixNano()
|
|
|
|
if windowStart != expectedStart {
|
|
t.Errorf("Expected window start %d, got %d", expectedStart, windowStart)
|
|
}
|
|
|
|
// 测试 nil TimeSlot
|
|
var nilTS *TimeSlot
|
|
nilWindowStart := nilTS.WindowStart()
|
|
if nilWindowStart != 0 {
|
|
t.Errorf("Expected WindowStart to return 0 for nil TimeSlot, got %d", nilWindowStart)
|
|
}
|
|
|
|
// 测试 Start 为 nil 的情况
|
|
tsWithNilStart := NewTimeSlot(nil, &end)
|
|
nilStart := tsWithNilStart.WindowStart()
|
|
if nilStart != 0 {
|
|
t.Errorf("Expected WindowStart to return 0 when Start is nil, got %d", nilStart)
|
|
}
|
|
}
|
|
|
|
// TestWindowEnd 测试 WindowEnd 方法
|
|
func TestWindowEnd(t *testing.T) {
|
|
start := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
end := time.Date(2024, 1, 1, 13, 0, 0, 0, time.UTC)
|
|
ts := NewTimeSlot(&start, &end)
|
|
|
|
windowEnd := ts.WindowEnd()
|
|
expectedEnd := end.UnixNano()
|
|
|
|
if windowEnd != expectedEnd {
|
|
t.Errorf("Expected window end %d, got %d", expectedEnd, windowEnd)
|
|
}
|
|
|
|
// 测试 nil TimeSlot
|
|
var nilTS *TimeSlot
|
|
nilWindowEnd := nilTS.WindowEnd()
|
|
if nilWindowEnd != 0 {
|
|
t.Errorf("Expected WindowEnd to return 0 for nil TimeSlot, got %d", nilWindowEnd)
|
|
}
|
|
|
|
// 测试 End 为 nil 的情况
|
|
tsWithNilEnd := NewTimeSlot(&start, nil)
|
|
nilEnd := tsWithNilEnd.WindowEnd()
|
|
if nilEnd != 0 {
|
|
t.Errorf("Expected WindowEnd to return 0 when End is nil, got %d", nilEnd)
|
|
}
|
|
}
|
|
|
|
// TestTimeSlotEdgeCases 测试 TimeSlot 的边界情况
|
|
func TestTimeSlotEdgeCases(t *testing.T) {
|
|
// 测试相同的开始和结束时间
|
|
sameTime := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
ts := NewTimeSlot(&sameTime, &sameTime)
|
|
|
|
if ts.Contains(sameTime) {
|
|
t.Error("Expected Contains to return false when start equals end")
|
|
}
|
|
|
|
// 测试开始时间晚于结束时间的情况
|
|
start := time.Date(2024, 1, 1, 13, 0, 0, 0, time.UTC)
|
|
end := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
invalidTS := NewTimeSlot(&start, &end)
|
|
|
|
midTime := time.Date(2024, 1, 1, 12, 30, 0, 0, time.UTC)
|
|
if invalidTS.Contains(midTime) {
|
|
t.Error("Expected Contains to return false for invalid time slot (start > end)")
|
|
}
|
|
}
|
|
|
|
// TestTimeSlotConcurrentAccess 测试 TimeSlot 的并发访问
|
|
func TestTimeSlotConcurrentAccess(t *testing.T) {
|
|
start := time.Date(2024, 1, 1, 12, 0, 0, 0, time.UTC)
|
|
end := time.Date(2024, 1, 1, 13, 0, 0, 0, time.UTC)
|
|
ts := NewTimeSlot(&start, &end)
|
|
|
|
// 启动多个 goroutine 并发访问 TimeSlot 方法
|
|
done := make(chan bool, 10)
|
|
for i := 0; i < 10; i++ {
|
|
go func() {
|
|
for j := 0; j < 100; j++ {
|
|
// 测试各种方法的并发访问
|
|
_ = ts.Hash()
|
|
_ = ts.Contains(start)
|
|
_ = ts.GetStartTime()
|
|
_ = ts.GetEndTime()
|
|
_ = ts.WindowStart()
|
|
_ = ts.WindowEnd()
|
|
}
|
|
done <- true
|
|
}()
|
|
}
|
|
|
|
// 等待所有 goroutine 完成
|
|
for i := 0; i < 10; i++ {
|
|
<-done
|
|
}
|
|
}
|