package testusers import ( "bytes" "fmt" "image" "image/png" "os" "path/filepath" "reflect" "regexp" "strings" "testing" "time" ) func TestGenerateBalancedLabelledAdults(t *testing.T) { items, err := Generate("https://im.bchongw.com/uploads/") if err != nil || len(items) != 100 { t.Fatalf("len=%d err=%v", len(items), err) } ids, names := map[string]bool{}, map[string]bool{} locations := map[string]bool{} counts := map[int]int{} files := map[string]bool{} for _, file := range Avatars() { files[file] = true } for _, p := range items { if ids[p.PublicID] || names[p.Nickname] || !p.IsTest || p.TestBatch != Batch || p.Label != "测试用户" || !strings.HasPrefix(p.Nickname, "测试·") { t.Fatalf("missing label or duplicate identity: %+v", p) } ids[p.PublicID], names[p.Nickname] = true, true counts[p.Gender]++ birthday, err := time.Parse("2006-01-02", p.Birthday) if err != nil || birthday.After(time.Date(2008, 8, 31, 0, 0, 0, 0, time.UTC)) { t.Fatalf("invalid adult birthday: %s", p.Birthday) } if !files[p.AvatarFile] || p.Avatar != "https://im.bchongw.com/uploads/"+p.AvatarFile || !regexp.MustCompile(`^[0-9]+-[0-9]+\.png$`).MatchString(p.AvatarFile) { t.Fatalf("avatar incompatible with media route: %s", p.Avatar) } if !strings.Contains(p.Bio, "非真实交友用户") { t.Fatal("missing synthetic identity disclosure") } if p.Latitude < 18 || p.Latitude > 54 || p.Longitude < 73 || p.Longitude > 135 { t.Fatalf("fixture location is outside China: %+v", p) } location := fmt.Sprintf("%.6f,%.6f", p.Latitude, p.Longitude) if locations[location] { t.Fatalf("duplicate fixture location: %s", location) } locations[location] = true } if counts[1] != 50 || counts[2] != 50 || len(counts) != 2 { t.Fatalf("gender distribution: %v", counts) } again, _ := Generate("https://im.bchongw.com/uploads/") if !reflect.DeepEqual(items, again) { t.Fatal("fixture generation must be deterministic") } } func TestRejectUnsafePublicBase(t *testing.T) { for _, base := range []string{"", "/uploads", "http://example.com/uploads", "https://user:secret@example.com/uploads", "https://example.com/uploads?x=1", "https://example.com/#bad", "javascript:alert(1)"} { if _, err := Generate(base); err == nil { t.Errorf("accepted unsafe base %q", base) } } for _, base := range []string{"https://example.com/uploads", "http://127.0.0.1:8888/uploads", "http://localhost:8888/uploads"} { if _, err := Generate(base); err != nil { t.Errorf("rejected valid base %q: %v", base, err) } } } func TestAvatarCopyIsRepeatableAndDoesNotOverwrite(t *testing.T) { source, destination := t.TempDir(), t.TempDir() var buf bytes.Buffer if err := png.Encode(&buf, image.NewRGBA(image.Rect(0, 0, 256, 256))); err != nil { t.Fatal(err) } for _, file := range Avatars() { if err := os.WriteFile(filepath.Join(source, file), buf.Bytes(), 0600); err != nil { t.Fatal(err) } } for i := 0; i < 2; i++ { if err := CopyAvatars(source, destination); err != nil { t.Fatal(err) } } conflict := filepath.Join(destination, Avatars()[0]) if err := os.WriteFile(conflict, []byte("existing user file"), 0600); err != nil { t.Fatal(err) } if err := CopyAvatars(source, destination); err == nil { t.Fatal("overwrote an unrelated file") } if got, _ := os.ReadFile(conflict); string(got) != "existing user file" { t.Fatal("collision changed existing file") } } func TestBundledAvatarsArePresent(t *testing.T) { if err := CopyAvatars(filepath.Join("..", "..", "..", "fixtures", "test-users", "avatars"), t.TempDir()); err != nil { t.Fatal(err) } }