mirror of
https://github.com/Mezeporta/Erupe.git
synced 2026-03-21 23:22:34 +01:00
386 lines
9.0 KiB
Go
386 lines
9.0 KiB
Go
package mhfcourse
|
|
|
|
import (
|
|
_config "erupe-ce/config"
|
|
"math"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
func TestCourse_Aliases(t *testing.T) {
|
|
tests := []struct {
|
|
id uint16
|
|
wantLen int
|
|
want []string
|
|
}{
|
|
{1, 2, []string{"Trial", "TL"}},
|
|
{2, 2, []string{"HunterLife", "HL"}},
|
|
{3, 3, []string{"Extra", "ExtraA", "EX"}},
|
|
{8, 4, []string{"Assist", "***ist", "Legend", "Rasta"}},
|
|
{26, 4, []string{"NetCafe", "Cafe", "OfficialCafe", "Official"}},
|
|
{13, 0, nil}, // Unknown course
|
|
{99, 0, nil}, // Unknown course
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(string(rune(tt.id)), func(t *testing.T) {
|
|
c := Course{ID: tt.id}
|
|
got := c.Aliases()
|
|
if len(got) != tt.wantLen {
|
|
t.Errorf("Course{ID: %d}.Aliases() length = %d, want %d", tt.id, len(got), tt.wantLen)
|
|
}
|
|
if tt.want != nil {
|
|
for i, alias := range tt.want {
|
|
if i >= len(got) || got[i] != alias {
|
|
t.Errorf("Course{ID: %d}.Aliases()[%d] = %q, want %q", tt.id, i, got[i], alias)
|
|
}
|
|
}
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCourses(t *testing.T) {
|
|
courses := Courses()
|
|
if len(courses) != 32 {
|
|
t.Errorf("Courses() length = %d, want 32", len(courses))
|
|
}
|
|
|
|
// Verify IDs are sequential from 0 to 31
|
|
for i, course := range courses {
|
|
if course.ID != uint16(i) {
|
|
t.Errorf("Courses()[%d].ID = %d, want %d", i, course.ID, i)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCourse_Value(t *testing.T) {
|
|
tests := []struct {
|
|
id uint16
|
|
expected uint32
|
|
}{
|
|
{0, 1}, // 2^0
|
|
{1, 2}, // 2^1
|
|
{2, 4}, // 2^2
|
|
{3, 8}, // 2^3
|
|
{4, 16}, // 2^4
|
|
{5, 32}, // 2^5
|
|
{10, 1024}, // 2^10
|
|
{15, 32768}, // 2^15
|
|
{20, 1048576}, // 2^20
|
|
{31, 2147483648}, // 2^31
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(string(rune(tt.id)), func(t *testing.T) {
|
|
c := Course{ID: tt.id}
|
|
got := c.Value()
|
|
if got != tt.expected {
|
|
t.Errorf("Course{ID: %d}.Value() = %d, want %d", tt.id, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCourseExists(t *testing.T) {
|
|
courses := []Course{
|
|
{ID: 1},
|
|
{ID: 5},
|
|
{ID: 10},
|
|
{ID: 15},
|
|
}
|
|
|
|
tests := []struct {
|
|
name string
|
|
id uint16
|
|
expected bool
|
|
}{
|
|
{"exists first", 1, true},
|
|
{"exists middle", 5, true},
|
|
{"exists last", 15, true},
|
|
{"not exists", 3, false},
|
|
{"not exists 0", 0, false},
|
|
{"not exists 20", 20, false},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
got := CourseExists(tt.id, courses)
|
|
if got != tt.expected {
|
|
t.Errorf("CourseExists(%d, courses) = %v, want %v", tt.id, got, tt.expected)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCourseExists_EmptySlice(t *testing.T) {
|
|
var courses []Course
|
|
if CourseExists(1, courses) {
|
|
t.Error("CourseExists(1, []) should return false for empty slice")
|
|
}
|
|
}
|
|
|
|
func TestGetCourseStruct(t *testing.T) {
|
|
// Save original config and restore after test
|
|
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
|
|
defer func() {
|
|
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
|
|
}()
|
|
|
|
// Set up test config
|
|
_config.ErupeConfig.DefaultCourses = []uint16{1, 2}
|
|
|
|
tests := []struct {
|
|
name string
|
|
rights uint32
|
|
wantMinLen int // Minimum expected courses (including defaults)
|
|
checkCourses []uint16
|
|
}{
|
|
{
|
|
name: "no rights",
|
|
rights: 0,
|
|
wantMinLen: 2, // Just default courses
|
|
checkCourses: []uint16{1, 2},
|
|
},
|
|
{
|
|
name: "course 3 only",
|
|
rights: 8, // 2^3
|
|
wantMinLen: 3, // defaults + course 3
|
|
checkCourses: []uint16{1, 2, 3},
|
|
},
|
|
{
|
|
name: "course 1",
|
|
rights: 2, // 2^1
|
|
wantMinLen: 2,
|
|
checkCourses: []uint16{1, 2},
|
|
},
|
|
{
|
|
name: "multiple courses",
|
|
rights: 2 + 8 + 32, // courses 1, 3, 5
|
|
wantMinLen: 4,
|
|
checkCourses: []uint16{1, 2, 3, 5},
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
courses, newRights := GetCourseStruct(tt.rights)
|
|
|
|
if len(courses) < tt.wantMinLen {
|
|
t.Errorf("GetCourseStruct(%d) returned %d courses, want at least %d", tt.rights, len(courses), tt.wantMinLen)
|
|
}
|
|
|
|
// Verify expected courses are present
|
|
for _, id := range tt.checkCourses {
|
|
found := false
|
|
for _, c := range courses {
|
|
if c.ID == id {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
t.Errorf("GetCourseStruct(%d) missing expected course ID %d", tt.rights, id)
|
|
}
|
|
}
|
|
|
|
// Verify newRights is a valid sum of course values
|
|
if newRights < tt.rights {
|
|
t.Logf("GetCourseStruct(%d) newRights = %d (may include additional courses)", tt.rights, newRights)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestGetCourseStruct_NetcafeCourse(t *testing.T) {
|
|
// Save original config
|
|
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
|
|
defer func() {
|
|
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
|
|
}()
|
|
_config.ErupeConfig.DefaultCourses = []uint16{}
|
|
|
|
// Course 26 (NetCafe) should add course 25
|
|
courses, _ := GetCourseStruct(1 << 26)
|
|
|
|
hasNetcafe := false
|
|
hasCafeSP := false
|
|
hasRealNetcafe := false
|
|
for _, c := range courses {
|
|
if c.ID == 26 {
|
|
hasNetcafe = true
|
|
}
|
|
if c.ID == 25 {
|
|
hasCafeSP = true
|
|
}
|
|
if c.ID == 30 {
|
|
hasRealNetcafe = true
|
|
}
|
|
}
|
|
|
|
if !hasNetcafe {
|
|
t.Error("Course 26 (NetCafe) should be present")
|
|
}
|
|
if !hasCafeSP {
|
|
t.Error("Course 25 should be added when course 26 is present")
|
|
}
|
|
if !hasRealNetcafe {
|
|
t.Error("Course 30 should be added when course 26 is present")
|
|
}
|
|
}
|
|
|
|
func TestGetCourseStruct_NCourse(t *testing.T) {
|
|
// Save original config
|
|
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
|
|
defer func() {
|
|
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
|
|
}()
|
|
_config.ErupeConfig.DefaultCourses = []uint16{}
|
|
|
|
// Course 9 should add course 30
|
|
courses, _ := GetCourseStruct(1 << 9)
|
|
|
|
hasNCourse := false
|
|
hasRealNetcafe := false
|
|
for _, c := range courses {
|
|
if c.ID == 9 {
|
|
hasNCourse = true
|
|
}
|
|
if c.ID == 30 {
|
|
hasRealNetcafe = true
|
|
}
|
|
}
|
|
|
|
if !hasNCourse {
|
|
t.Error("Course 9 (N) should be present")
|
|
}
|
|
if !hasRealNetcafe {
|
|
t.Error("Course 30 should be added when course 9 is present")
|
|
}
|
|
}
|
|
|
|
func TestGetCourseStruct_HidenCourse(t *testing.T) {
|
|
// Save original config
|
|
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
|
|
defer func() {
|
|
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
|
|
}()
|
|
_config.ErupeConfig.DefaultCourses = []uint16{}
|
|
|
|
// Course 10 (Hiden) should add course 31
|
|
courses, _ := GetCourseStruct(1 << 10)
|
|
|
|
hasHiden := false
|
|
hasHidenExtra := false
|
|
for _, c := range courses {
|
|
if c.ID == 10 {
|
|
hasHiden = true
|
|
}
|
|
if c.ID == 31 {
|
|
hasHidenExtra = true
|
|
}
|
|
}
|
|
|
|
if !hasHiden {
|
|
t.Error("Course 10 (Hiden) should be present")
|
|
}
|
|
if !hasHidenExtra {
|
|
t.Error("Course 31 should be added when course 10 is present")
|
|
}
|
|
}
|
|
|
|
func TestGetCourseStruct_ExpiryDate(t *testing.T) {
|
|
// Save original config
|
|
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
|
|
defer func() {
|
|
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
|
|
}()
|
|
_config.ErupeConfig.DefaultCourses = []uint16{}
|
|
|
|
courses, _ := GetCourseStruct(1 << 3)
|
|
|
|
expectedExpiry := time.Date(2030, 1, 1, 0, 0, 0, 0, time.FixedZone("UTC+9", 9*60*60))
|
|
|
|
for _, c := range courses {
|
|
if c.ID == 3 && !c.Expiry.IsZero() {
|
|
if !c.Expiry.Equal(expectedExpiry) {
|
|
t.Errorf("Course expiry = %v, want %v", c.Expiry, expectedExpiry)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGetCourseStruct_ReturnsRecalculatedRights(t *testing.T) {
|
|
// Save original config
|
|
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
|
|
defer func() {
|
|
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
|
|
}()
|
|
_config.ErupeConfig.DefaultCourses = []uint16{}
|
|
|
|
courses, newRights := GetCourseStruct(2 + 8 + 32) // courses 1, 3, 5
|
|
|
|
// Calculate expected rights from returned courses
|
|
var expectedRights uint32
|
|
for _, c := range courses {
|
|
expectedRights += c.Value()
|
|
}
|
|
|
|
if newRights != expectedRights {
|
|
t.Errorf("GetCourseStruct() newRights = %d, want %d (sum of returned course values)", newRights, expectedRights)
|
|
}
|
|
}
|
|
|
|
func TestCourse_ValueMatchesPowerOfTwo(t *testing.T) {
|
|
// Verify that Value() correctly implements 2^ID
|
|
for id := uint16(0); id < 32; id++ {
|
|
c := Course{ID: id}
|
|
expected := uint32(math.Pow(2, float64(id)))
|
|
got := c.Value()
|
|
if got != expected {
|
|
t.Errorf("Course{ID: %d}.Value() = %d, want %d", id, got, expected)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkCourse_Value(b *testing.B) {
|
|
c := Course{ID: 15}
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_ = c.Value()
|
|
}
|
|
}
|
|
|
|
func BenchmarkCourseExists(b *testing.B) {
|
|
courses := []Course{
|
|
{ID: 1}, {ID: 2}, {ID: 3}, {ID: 4}, {ID: 5},
|
|
{ID: 10}, {ID: 15}, {ID: 20}, {ID: 25}, {ID: 30},
|
|
}
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_ = CourseExists(15, courses)
|
|
}
|
|
}
|
|
|
|
func BenchmarkGetCourseStruct(b *testing.B) {
|
|
// Save original config
|
|
originalDefaultCourses := _config.ErupeConfig.DefaultCourses
|
|
defer func() {
|
|
_config.ErupeConfig.DefaultCourses = originalDefaultCourses
|
|
}()
|
|
_config.ErupeConfig.DefaultCourses = []uint16{1, 2}
|
|
|
|
rights := uint32(2 + 8 + 32 + 128 + 512)
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_, _ = GetCourseStruct(rights)
|
|
}
|
|
}
|
|
|
|
func BenchmarkCourses(b *testing.B) {
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
_ = Courses()
|
|
}
|
|
}
|