497 lines
12 KiB
Go
497 lines
12 KiB
Go
package main
|
||
|
||
import (
|
||
"fmt"
|
||
"os"
|
||
"testing"
|
||
)
|
||
|
||
// createTestDictFile creates a temporary dict file for testing
|
||
func createTestDictFile(t *testing.T, content string) string {
|
||
tmpFile, err := os.CreateTemp("", "test_dict_*.txt")
|
||
if err != nil {
|
||
t.Fatalf("Failed to create temp file: %v", err)
|
||
}
|
||
|
||
_, err = tmpFile.WriteString(content)
|
||
if err != nil {
|
||
t.Fatalf("Failed to write to temp file: %v", err)
|
||
}
|
||
|
||
tmpFile.Close()
|
||
return tmpFile.Name()
|
||
}
|
||
|
||
func TestDictE2E(t *testing.T) {
|
||
dict, err := NewChineseDict("dict.txt")
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
for range 1000 {
|
||
char := dict.GetRandomCharacter()
|
||
fmt.Printf("%c", char)
|
||
if char == 0 {
|
||
t.Error("GetRandomCharacter returned null rune")
|
||
}
|
||
}
|
||
fmt.Println()
|
||
|
||
count := dict.GetCharacterCount()
|
||
if count == 0 {
|
||
t.Error("GetCharacterCount returned 0")
|
||
}
|
||
|
||
count = dict.GetLineCount()
|
||
if count == 0 {
|
||
t.Error("GetLineCount returned 0")
|
||
}
|
||
}
|
||
|
||
func TestDictE2ESingleLineVer(t *testing.T) {
|
||
dict, err := NewChineseDict("random_char.txt")
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
for range 1000 {
|
||
char := dict.GetRandomCharacter()
|
||
fmt.Printf("%c", char)
|
||
if char == 0 {
|
||
t.Error("GetRandomCharacter returned null rune")
|
||
}
|
||
}
|
||
fmt.Println()
|
||
|
||
count := dict.GetCharacterCount()
|
||
if count == 0 {
|
||
t.Error("GetCharacterCount returned 0")
|
||
}
|
||
|
||
count = dict.GetLineCount()
|
||
if count == 0 {
|
||
t.Error("GetLineCount returned 0")
|
||
}
|
||
}
|
||
|
||
func TestNewChineseDict(t *testing.T) {
|
||
testContent := `大家好大家好,家人们晚上好
|
||
先点点关注不迷路,点个小红心
|
||
Hello world test 测试`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
if dict == nil {
|
||
t.Fatal("NewChineseDict returned nil dictionary")
|
||
}
|
||
|
||
expectedLines := 3
|
||
if len(dict.lines) != expectedLines {
|
||
t.Errorf("Expected %d lines, got %d", expectedLines, len(dict.lines))
|
||
}
|
||
|
||
// Check initial state
|
||
if dict.currentLineIndex != -1 {
|
||
t.Errorf("Expected currentLineIndex to be -1, got %d", dict.currentLineIndex)
|
||
}
|
||
|
||
if dict.currentCharIndex != 0 {
|
||
t.Errorf("Expected currentCharIndex to be 0, got %d", dict.currentCharIndex)
|
||
}
|
||
}
|
||
|
||
func TestNewChineseDictWithEmptyLines(t *testing.T) {
|
||
testContent := `大家好大家好
|
||
|
||
先点点关注不迷路
|
||
|
||
Hello world test`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
expectedLines := 3 // Empty lines should be filtered out
|
||
if len(dict.lines) != expectedLines {
|
||
t.Errorf("Expected %d lines (empty lines filtered), got %d", expectedLines, len(dict.lines))
|
||
}
|
||
}
|
||
|
||
func TestNewChineseDictFileNotFound(t *testing.T) {
|
||
_, err := NewChineseDict("nonexistent_file.txt")
|
||
if err == nil {
|
||
t.Error("Expected error for nonexistent file, got nil")
|
||
}
|
||
}
|
||
|
||
func TestIsValidCharacter(t *testing.T) {
|
||
dict := &ChineseDict{}
|
||
|
||
testCases := []struct {
|
||
char rune
|
||
expected bool
|
||
desc string
|
||
}{
|
||
{'大', true, "Chinese character"},
|
||
{'家', true, "Chinese character"},
|
||
{'好', true, "Chinese character"},
|
||
{'a', true, "English lowercase"},
|
||
{'Z', true, "English uppercase"},
|
||
{'H', true, "English uppercase"},
|
||
{',', false, "Comma punctuation"},
|
||
{',', false, "Chinese comma"},
|
||
{' ', false, "Space"},
|
||
{'!', false, "Exclamation mark"},
|
||
{'。', false, "Chinese period"},
|
||
{'1', false, "Number"},
|
||
{'@', false, "Symbol"},
|
||
{'\n', false, "Newline"},
|
||
}
|
||
|
||
for _, tc := range testCases {
|
||
result := dict.isValidCharacter(tc.char)
|
||
if result != tc.expected {
|
||
t.Errorf("isValidCharacter('%c') for %s: expected %v, got %v",
|
||
tc.char, tc.desc, tc.expected, result)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestGetRandomCharacter(t *testing.T) {
|
||
testContent := `大家好abc
|
||
Hello世界
|
||
测试Test`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
// Test getting characters
|
||
validChars := make(map[rune]bool)
|
||
for i := 0; i < 50; i++ { // Get multiple characters to test randomness
|
||
char := dict.GetRandomCharacter()
|
||
if char == 0 {
|
||
t.Error("GetRandomCharacter returned null rune")
|
||
}
|
||
if !dict.isValidCharacter(char) {
|
||
t.Errorf("GetRandomCharacter returned invalid character: '%c'", char)
|
||
}
|
||
validChars[char] = true
|
||
}
|
||
|
||
// Should have gotten some variety of characters
|
||
if len(validChars) < 5 {
|
||
t.Errorf("Expected more variety in characters, got only %d unique chars", len(validChars))
|
||
}
|
||
}
|
||
|
||
func TestGetRandomCharacterEmptyDict(t *testing.T) {
|
||
dict := &ChineseDict{lines: []string{}}
|
||
|
||
char := dict.GetRandomCharacter()
|
||
if char != 0 {
|
||
t.Errorf("Expected null rune for empty dict, got '%c'", char)
|
||
}
|
||
}
|
||
|
||
func TestGetRandomCharacterOnlyPunctuation(t *testing.T) {
|
||
testContent := `,。!?
|
||
!@#$%
|
||
,,,。。。`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
// This should handle lines with only punctuation gracefully
|
||
// The function should try all lines and return null when no valid characters found
|
||
char := dict.GetRandomCharacter()
|
||
if char != 0 {
|
||
t.Errorf("Expected null rune for punctuation-only dict, got '%c'", char)
|
||
}
|
||
}
|
||
|
||
func TestGetRandomString(t *testing.T) {
|
||
testContent := `大家好abc
|
||
Hello世界
|
||
测试Test`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
// Test different lengths
|
||
testLengths := []int{1, 5, 10, 20}
|
||
|
||
for _, length := range testLengths {
|
||
result := dict.GetRandomString(length)
|
||
runes := []rune(result)
|
||
|
||
if len(runes) != length {
|
||
t.Errorf("GetRandomString(%d): expected length %d, got %d",
|
||
length, length, len(runes))
|
||
}
|
||
|
||
// Verify all characters are valid
|
||
for _, r := range runes {
|
||
if !dict.isValidCharacter(r) {
|
||
t.Errorf("GetRandomString returned invalid character: '%c'", r)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestGetRandomStringZeroLength(t *testing.T) {
|
||
testContent := `大家好`
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
result := dict.GetRandomString(0)
|
||
if result != "" {
|
||
t.Errorf("Expected empty string for length 0, got '%s'", result)
|
||
}
|
||
|
||
result = dict.GetRandomString(-1)
|
||
if result != "" {
|
||
t.Errorf("Expected empty string for negative length, got '%s'", result)
|
||
}
|
||
}
|
||
|
||
func TestGetRandomStringEmptyDict(t *testing.T) {
|
||
dict := &ChineseDict{lines: []string{}}
|
||
|
||
result := dict.GetRandomString(5)
|
||
if result != "" {
|
||
t.Errorf("Expected empty string for empty dict, got '%s'", result)
|
||
}
|
||
}
|
||
|
||
func TestGetLineCount(t *testing.T) {
|
||
testContent := `Line 1
|
||
Line 2
|
||
Line 3
|
||
|
||
Line 5`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
expectedCount := 4 // Empty line should be filtered out
|
||
count := dict.GetLineCount()
|
||
if count != expectedCount {
|
||
t.Errorf("Expected line count %d, got %d", expectedCount, count)
|
||
}
|
||
}
|
||
|
||
func TestGetCharacterCount(t *testing.T) {
|
||
testContent := `大家好abc!
|
||
Hello世界,
|
||
测试Test。`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
count := dict.GetCharacterCount()
|
||
|
||
// Count manually: 大家好abc + Hello世界 + 测试Test = 3+3 + 5+2 + 2+4 = 19 valid chars
|
||
expectedCount := 19
|
||
if count != expectedCount {
|
||
t.Errorf("Expected character count %d, got %d", expectedCount, count)
|
||
}
|
||
}
|
||
|
||
func TestSelectNewRandomLine(t *testing.T) {
|
||
testContent := `Line 1
|
||
Line 2
|
||
Line 3`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
// Test multiple selections to ensure randomness
|
||
selectedLines := make(map[int]bool)
|
||
for i := 0; i < 20; i++ {
|
||
dict.selectNewRandomLine()
|
||
if dict.currentLineIndex < 0 || dict.currentLineIndex >= len(dict.lines) {
|
||
t.Errorf("selectNewRandomLine set invalid index: %d", dict.currentLineIndex)
|
||
}
|
||
if dict.currentCharIndex != 0 {
|
||
t.Errorf("selectNewRandomLine should reset currentCharIndex to 0, got %d", dict.currentCharIndex)
|
||
}
|
||
selectedLines[dict.currentLineIndex] = true
|
||
}
|
||
|
||
// Should have selected different lines (with high probability)
|
||
if len(selectedLines) < 2 {
|
||
t.Error("selectNewRandomLine appears to not be random enough")
|
||
}
|
||
}
|
||
|
||
func TestCharacterSequencing(t *testing.T) {
|
||
// Test that characters are returned in sequence from lines
|
||
testContent := `abc
|
||
def`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
// Get enough characters to likely exhaust at least one line
|
||
chars := make([]rune, 10)
|
||
for i := 0; i < 10; i++ {
|
||
chars[i] = dict.GetRandomCharacter()
|
||
}
|
||
|
||
// Verify we got valid characters
|
||
for i, char := range chars {
|
||
if !dict.isValidCharacter(char) {
|
||
t.Errorf("Character at position %d is invalid: '%c'", i, char)
|
||
}
|
||
}
|
||
|
||
// Should contain characters from our test content
|
||
validTestChars := map[rune]bool{'a': true, 'b': true, 'c': true, 'd': true, 'e': true, 'f': true}
|
||
for _, char := range chars {
|
||
if !validTestChars[char] {
|
||
t.Errorf("Got unexpected character: '%c'", char)
|
||
}
|
||
}
|
||
}
|
||
|
||
func TestMixedLanguageContent(t *testing.T) {
|
||
testContent := `Hello世界!This is 测试。
|
||
English中文Mixed内容,with punctuation!
|
||
Another行with more混合content。`
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
// Get many characters and verify they're all valid
|
||
chineseCount := 0
|
||
englishCount := 0
|
||
|
||
for i := 0; i < 100; i++ {
|
||
char := dict.GetRandomCharacter()
|
||
if char == 0 {
|
||
t.Error("Got null character")
|
||
continue
|
||
}
|
||
|
||
if !dict.isValidCharacter(char) {
|
||
t.Errorf("Got invalid character: '%c' (U+%04X)", char, char)
|
||
continue
|
||
}
|
||
|
||
if char >= 0x4E00 && char <= 0x9FFF {
|
||
chineseCount++
|
||
} else if (char >= 'a' && char <= 'z') || (char >= 'A' && char <= 'Z') {
|
||
englishCount++
|
||
}
|
||
}
|
||
|
||
// Should have gotten both Chinese and English characters
|
||
if chineseCount == 0 {
|
||
t.Error("Expected some Chinese characters, got none")
|
||
}
|
||
if englishCount == 0 {
|
||
t.Error("Expected some English characters, got none")
|
||
}
|
||
|
||
t.Logf("Got %d Chinese and %d English characters", chineseCount, englishCount)
|
||
}
|
||
|
||
func TestSingleLineContent(t *testing.T) {
|
||
testContent := `华枝睾吸虫豆卷叶野螟小叶榕木`
|
||
//黄眉企鹅五房` for multiline false test
|
||
|
||
tmpFile := createTestDictFile(t, testContent)
|
||
defer os.Remove(tmpFile)
|
||
|
||
dict, err := NewChineseDict(tmpFile)
|
||
if err != nil {
|
||
t.Fatalf("NewChineseDict failed: %v", err)
|
||
}
|
||
|
||
runeInPosition := 0
|
||
currentPosition := -1
|
||
|
||
for range 100 {
|
||
char := dict.GetRandomCharacter()
|
||
if char == 0 {
|
||
t.Error("Got null character")
|
||
continue
|
||
}
|
||
|
||
if !dict.isValidCharacter(char) {
|
||
t.Errorf("Got invalid character: '%c' (U+%04X)", char, char)
|
||
continue
|
||
}
|
||
|
||
if char == '华' || char == '黄' {
|
||
currentPosition = 0
|
||
}
|
||
|
||
if currentPosition+1 == dict.currentCharIndex {
|
||
runeInPosition++
|
||
currentPosition++
|
||
}
|
||
}
|
||
|
||
if runeInPosition == 100 {
|
||
t.Error("GetRandomCharacter is not random enough, always returning characters in sequence")
|
||
}
|
||
|
||
t.Logf("Rune in position: %d", runeInPosition)
|
||
}
|