tests(common): comprehensive code coverage for common

This commit is contained in:
Houmgaor
2025-10-27 12:59:22 +01:00
parent d3fd0c72b0
commit a6cf550fdb
11 changed files with 3949 additions and 0 deletions

View File

@@ -0,0 +1,385 @@
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()
}
}