Files
2025-08-07 19:23:48 +08:00

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
}
}