235 lines
5.1 KiB
Go
235 lines
5.1 KiB
Go
package parser
|
||
|
||
import (
|
||
"os"
|
||
"path/filepath"
|
||
"testing"
|
||
|
||
"jwts/models"
|
||
)
|
||
|
||
func TestParseScheduleHTML_FromTestHTML_MergedWeeks(t *testing.T) {
|
||
htmlPath := filepath.Join("..", "test.html")
|
||
body, err := os.ReadFile(htmlPath)
|
||
if err != nil {
|
||
t.Fatalf("读取 test.html 失败: %v", err)
|
||
}
|
||
|
||
courses, err := ParseScheduleHTML(string(body))
|
||
if err != nil {
|
||
t.Fatalf("解析课表失败: %v", err)
|
||
}
|
||
|
||
checkCourseHasWeek(t, courses, "大学物理X(1)", "王小赛", 1)
|
||
checkCourseHasWeek(t, courses, "大学物理X(1)", "王小赛", 16)
|
||
checkCourseHasWeek(t, courses, "数学分析(2)", "于战华", 2)
|
||
checkCourseHasWeek(t, courses, "数学分析(2)", "于战华", 15)
|
||
checkCourseHasRooms(t, courses, "中国近现代史纲要", "苏克", []string{"H楼-447", "H楼-434"})
|
||
}
|
||
|
||
func TestParseScheduleHTML_FromGrkbHTML_ChineseCommaWeeks(t *testing.T) {
|
||
htmlPath := filepath.Join("..", "grkb.html")
|
||
body, err := os.ReadFile(htmlPath)
|
||
if err != nil {
|
||
t.Fatalf("读取 grkb.html 失败: %v", err)
|
||
}
|
||
|
||
courses, err := ParseScheduleHTML(string(body))
|
||
if err != nil {
|
||
t.Fatalf("解析课表失败: %v", err)
|
||
}
|
||
|
||
checkCourseHasWeek(t, courses, "数理统计", "黄春茂", 10)
|
||
checkCourseHasWeek(t, courses, "数理统计", "黄春茂", 11)
|
||
checkCourseHasWeek(t, courses, "数理统计", "黄春茂", 12)
|
||
checkCourseHasWeek(t, courses, "微分几何", "李鹏程", 2)
|
||
checkCourseHasWeek(t, courses, "微分几何", "李鹏程", 8)
|
||
checkCourseHasWeek(t, courses, "微分几何", "李鹏程", 9)
|
||
checkCourseRoomForWeek(t, courses, "微分几何", "李鹏程", 9, "N楼-331")
|
||
checkCourseRoomForWeek(t, courses, "微分几何", "李鹏程", 8, "N楼-335")
|
||
}
|
||
|
||
func checkCourseWeeks(
|
||
t *testing.T,
|
||
courses []models.Course,
|
||
name, teacher, day string,
|
||
section []int,
|
||
wantStart, wantEnd int,
|
||
) {
|
||
t.Helper()
|
||
|
||
for _, c := range courses {
|
||
if c.Name != name || c.Teacher != teacher {
|
||
continue
|
||
}
|
||
for _, s := range c.Schedule {
|
||
if s.Day != day || !sameInts(s.Section, section) {
|
||
continue
|
||
}
|
||
if len(s.Weeks) == 0 {
|
||
t.Fatalf("%s/%s 周次为空", name, teacher)
|
||
}
|
||
if s.Weeks[0] != wantStart || s.Weeks[len(s.Weeks)-1] != wantEnd {
|
||
t.Fatalf("%s/%s 周次范围错误: got=%v want=%d..%d", name, teacher, s.Weeks, wantStart, wantEnd)
|
||
}
|
||
return
|
||
}
|
||
}
|
||
|
||
t.Fatalf("未找到课程: %s/%s day=%s section=%v", name, teacher, day, section)
|
||
}
|
||
|
||
func sameInts(a, b []int) bool {
|
||
if len(a) != len(b) {
|
||
return false
|
||
}
|
||
for i := range a {
|
||
if a[i] != b[i] {
|
||
return false
|
||
}
|
||
}
|
||
return true
|
||
}
|
||
|
||
func checkScheduleContainsWeeks(
|
||
t *testing.T,
|
||
courses []models.Course,
|
||
name, teacher, day string,
|
||
section []int,
|
||
wantWeeks []int,
|
||
) {
|
||
t.Helper()
|
||
|
||
for _, c := range courses {
|
||
if c.Name != name || c.Teacher != teacher {
|
||
continue
|
||
}
|
||
for _, s := range c.Schedule {
|
||
if s.Day != day || !sameInts(s.Section, section) {
|
||
continue
|
||
}
|
||
if len(s.Weeks) == 0 {
|
||
t.Fatalf("%s/%s 周次为空", name, teacher)
|
||
}
|
||
for _, w := range wantWeeks {
|
||
if !containsInt(s.Weeks, w) {
|
||
t.Fatalf("%s/%s 周次缺失: want include=%d got=%v", name, teacher, w, s.Weeks)
|
||
}
|
||
}
|
||
return
|
||
}
|
||
}
|
||
|
||
t.Fatalf("未找到课程: %s/%s day=%s section=%v", name, teacher, day, section)
|
||
}
|
||
|
||
func containsInt(arr []int, target int) bool {
|
||
for _, v := range arr {
|
||
if v == target {
|
||
return true
|
||
}
|
||
}
|
||
return false
|
||
}
|
||
|
||
func checkCourseHasWeek(
|
||
t *testing.T,
|
||
courses []models.Course,
|
||
name, teacher string,
|
||
week int,
|
||
) {
|
||
t.Helper()
|
||
|
||
for _, c := range courses {
|
||
if c.Name != name || c.Teacher != teacher {
|
||
continue
|
||
}
|
||
for _, s := range c.Schedule {
|
||
if containsInt(s.Weeks, week) {
|
||
return
|
||
}
|
||
}
|
||
}
|
||
|
||
t.Fatalf("%s/%s 缺少第%d周", name, teacher, week)
|
||
}
|
||
|
||
func checkCourseRoomForWeek(
|
||
t *testing.T,
|
||
courses []models.Course,
|
||
name, teacher string,
|
||
week int,
|
||
wantRoom string,
|
||
) {
|
||
t.Helper()
|
||
|
||
for _, c := range courses {
|
||
if c.Name != name || c.Teacher != teacher {
|
||
continue
|
||
}
|
||
for _, s := range c.Schedule {
|
||
if containsInt(s.Weeks, week) && c.Room == wantRoom {
|
||
return
|
||
}
|
||
}
|
||
}
|
||
|
||
t.Fatalf("%s/%s 第%d周未匹配到地点 %s", name, teacher, week, wantRoom)
|
||
}
|
||
|
||
func checkCourseHasRooms(
|
||
t *testing.T,
|
||
courses []models.Course,
|
||
name, teacher string,
|
||
wantRooms []string,
|
||
) {
|
||
t.Helper()
|
||
|
||
roomSet := map[string]bool{}
|
||
for _, c := range courses {
|
||
if c.Name == name && c.Teacher == teacher {
|
||
roomSet[c.Room] = true
|
||
}
|
||
}
|
||
|
||
for _, room := range wantRooms {
|
||
if !roomSet[room] {
|
||
t.Fatalf("%s/%s 缺少地点: %s, 当前地点集合: %v", name, teacher, room, roomSet)
|
||
}
|
||
}
|
||
}
|
||
|
||
func checkCourseAnyScheduleContainsWeeks(
|
||
t *testing.T,
|
||
courses []models.Course,
|
||
name, teacher string,
|
||
wantWeeks []int,
|
||
) {
|
||
t.Helper()
|
||
|
||
foundCourse := false
|
||
for _, c := range courses {
|
||
if c.Name != name || c.Teacher != teacher {
|
||
continue
|
||
}
|
||
foundCourse = true
|
||
for _, s := range c.Schedule {
|
||
allFound := true
|
||
for _, w := range wantWeeks {
|
||
if !containsInt(s.Weeks, w) {
|
||
allFound = false
|
||
break
|
||
}
|
||
}
|
||
if allFound {
|
||
return
|
||
}
|
||
}
|
||
}
|
||
|
||
if !foundCourse {
|
||
t.Fatalf("未找到课程: %s/%s", name, teacher)
|
||
}
|
||
t.Fatalf("%s/%s 所有排课都不包含预期周次: want=%v", name, teacher, wantWeeks)
|
||
}
|