|
1 | 1 | package main |
2 | 2 |
|
3 | 3 | import ( |
| 4 | + "context" |
| 5 | + "database/sql" |
| 6 | + "fmt" |
| 7 | + "strings" |
4 | 8 | "testing" |
| 9 | + "time" |
| 10 | + |
| 11 | + _ "github.com/mattn/go-sqlite3" |
| 12 | + "maunium.net/go/mautrix/event" |
| 13 | + "maunium.net/go/mautrix/id" |
5 | 14 | ) |
6 | 15 |
|
7 | 16 | func TestExtractLinks(t *testing.T) { |
@@ -289,3 +298,150 @@ func splitLines(s string) []string { |
289 | 298 | } |
290 | 299 | return lines |
291 | 300 | } |
| 301 | + |
| 302 | +func TestUwuify(t *testing.T) { |
| 303 | + tests := []struct { |
| 304 | + name string |
| 305 | + input string |
| 306 | + check func(string) bool |
| 307 | + desc string |
| 308 | + }{ |
| 309 | + { |
| 310 | + "replaces r/l with w", |
| 311 | + "really cool", |
| 312 | + func(s string) bool { return strings.Contains(s, "w") }, |
| 313 | + "should replace r and l with w", |
| 314 | + }, |
| 315 | + { |
| 316 | + "replaces th with d", |
| 317 | + "the weather", |
| 318 | + func(s string) bool { return strings.Contains(s, "da") && strings.Contains(s, "wead") }, |
| 319 | + "should replace 'the ' with 'da ' and 'th' with 'd'", |
| 320 | + }, |
| 321 | + { |
| 322 | + "replaces love with wuv", |
| 323 | + "I love you", |
| 324 | + func(s string) bool { return strings.Contains(s, "wuv") }, |
| 325 | + "should replace love with wuv", |
| 326 | + }, |
| 327 | + { |
| 328 | + "appends kaomoji", |
| 329 | + "hello world", |
| 330 | + func(s string) bool { |
| 331 | + faces := []string{"uwu", "owo", ">w<", "^w^", "◕ᴗ◕✿", "✧w✧", "~nyaa"} |
| 332 | + for _, f := range faces { |
| 333 | + if strings.HasSuffix(s, f) { |
| 334 | + return true |
| 335 | + } |
| 336 | + } |
| 337 | + return false |
| 338 | + }, |
| 339 | + "should end with a kaomoji", |
| 340 | + }, |
| 341 | + } |
| 342 | + for _, tt := range tests { |
| 343 | + t.Run(tt.name, func(t *testing.T) { |
| 344 | + got := uwuify(tt.input) |
| 345 | + if !tt.check(got) { |
| 346 | + t.Errorf("uwuify(%q) = %q: %s", tt.input, got, tt.desc) |
| 347 | + } |
| 348 | + }) |
| 349 | + } |
| 350 | +} |
| 351 | + |
| 352 | +func TestQueryTopYappers(t *testing.T) { |
| 353 | + db, err := sql.Open("sqlite3", ":memory:") |
| 354 | + if err != nil { |
| 355 | + t.Fatalf("open db: %v", err) |
| 356 | + } |
| 357 | + defer db.Close() |
| 358 | + |
| 359 | + _, err = db.Exec(`CREATE TABLE IF NOT EXISTS messages ( |
| 360 | + id TEXT PRIMARY KEY, |
| 361 | + room_id TEXT, |
| 362 | + sender TEXT, |
| 363 | + ts_ms INTEGER, |
| 364 | + body TEXT, |
| 365 | + msgtype TEXT, |
| 366 | + raw_json TEXT |
| 367 | + )`) |
| 368 | + if err != nil { |
| 369 | + t.Fatalf("create table: %v", err) |
| 370 | + } |
| 371 | + |
| 372 | + now := time.Now().UnixMilli() |
| 373 | + room := "!testroom:example.com" |
| 374 | + |
| 375 | + // Insert test messages: alice=5, bob=3, carol=1, plus some bot messages that should be excluded. |
| 376 | + for i := 0; i < 5; i++ { |
| 377 | + _, _ = db.Exec(`INSERT INTO messages(id, room_id, sender, ts_ms, body, msgtype) VALUES (?, ?, ?, ?, ?, ?)`, |
| 378 | + fmt.Sprintf("alice-%d", i), room, "@alice:example.com", now-int64(i*1000), fmt.Sprintf("hello %d", i), "m.text") |
| 379 | + } |
| 380 | + for i := 0; i < 3; i++ { |
| 381 | + _, _ = db.Exec(`INSERT INTO messages(id, room_id, sender, ts_ms, body, msgtype) VALUES (?, ?, ?, ?, ?, ?)`, |
| 382 | + fmt.Sprintf("bob-%d", i), room, "@bob:example.com", now-int64(i*1000), fmt.Sprintf("hey %d", i), "m.text") |
| 383 | + } |
| 384 | + _, _ = db.Exec(`INSERT INTO messages(id, room_id, sender, ts_ms, body, msgtype) VALUES (?, ?, ?, ?, ?, ?)`, |
| 385 | + "carol-0", room, "@carol:example.com", now, "sup", "m.text") |
| 386 | + |
| 387 | + // Bot messages — should be excluded. |
| 388 | + _, _ = db.Exec(`INSERT INTO messages(id, room_id, sender, ts_ms, body, msgtype) VALUES (?, ?, ?, ?, ?, ?)`, |
| 389 | + "bot-1", room, "@bot:example.com", now, "[BOT] hello", "m.text") |
| 390 | + _, _ = db.Exec(`INSERT INTO messages(id, room_id, sender, ts_ms, body, msgtype) VALUES (?, ?, ?, ?, ?, ?)`, |
| 391 | + "bot-2", room, "@bot:example.com", now, "/bot help", "m.text") |
| 392 | + |
| 393 | + // Old message — should be excluded (>24h ago). |
| 394 | + _, _ = db.Exec(`INSERT INTO messages(id, room_id, sender, ts_ms, body, msgtype) VALUES (?, ?, ?, ?, ?, ?)`, |
| 395 | + "old-1", room, "@old:example.com", now-100000000, "ancient msg", "m.text") |
| 396 | + |
| 397 | + // Different room — should be excluded. |
| 398 | + _, _ = db.Exec(`INSERT INTO messages(id, room_id, sender, ts_ms, body, msgtype) VALUES (?, ?, ?, ?, ?, ?)`, |
| 399 | + "other-1", "!otherroom:example.com", "@other:example.com", now, "wrong room", "m.text") |
| 400 | + |
| 401 | + ev := &event.Event{ |
| 402 | + RoomID: id.RoomID(room), |
| 403 | + } |
| 404 | + |
| 405 | + ctx := context.Background() |
| 406 | + |
| 407 | + // Test default (top 5). |
| 408 | + result, err := queryTopYappers(ctx, db, nil, ev, "", "", false) |
| 409 | + if err != nil { |
| 410 | + t.Fatalf("queryTopYappers: %v", err) |
| 411 | + } |
| 412 | + if !strings.Contains(result, "alice") { |
| 413 | + t.Errorf("expected alice in result, got: %s", result) |
| 414 | + } |
| 415 | + if !strings.Contains(result, "5 msgs") { |
| 416 | + t.Errorf("expected '5 msgs' for alice, got: %s", result) |
| 417 | + } |
| 418 | + if !strings.Contains(result, "bob") { |
| 419 | + t.Errorf("expected bob in result, got: %s", result) |
| 420 | + } |
| 421 | + // alice should be ranked #1. |
| 422 | + if !strings.Contains(result, "1. alice") { |
| 423 | + t.Errorf("expected alice at rank 1, got: %s", result) |
| 424 | + } |
| 425 | + |
| 426 | + // Test with limit. |
| 427 | + result2, err := queryTopYappers(ctx, db, nil, ev, "2", "", false) |
| 428 | + if err != nil { |
| 429 | + t.Fatalf("queryTopYappers with limit: %v", err) |
| 430 | + } |
| 431 | + lines := strings.Split(strings.TrimSpace(result2), "\n") |
| 432 | + // Header line + 2 results. |
| 433 | + if len(lines) != 3 { |
| 434 | + t.Errorf("expected 3 lines (header + 2 results), got %d: %s", len(lines), result2) |
| 435 | + } |
| 436 | + |
| 437 | + // Bot and old messages should not appear. |
| 438 | + if strings.Contains(result, "bot") { |
| 439 | + t.Errorf("bot messages should be excluded, got: %s", result) |
| 440 | + } |
| 441 | + if strings.Contains(result, "old") { |
| 442 | + t.Errorf("old messages should be excluded, got: %s", result) |
| 443 | + } |
| 444 | + if strings.Contains(result, "other") { |
| 445 | + t.Errorf("messages from other rooms should be excluded, got: %s", result) |
| 446 | + } |
| 447 | +} |
0 commit comments