Files
pawtoolbox/main_test.go
2026-08-26 07:30:25 +02:00

201 lines
5.3 KiB
Go

package main
import (
"net/netip"
"os"
"path/filepath"
"strings"
"testing"
"time"
)
func TestPasswordGeneratorRespectsMinimums(t *testing.T) {
o := PWOptions{Length: 20, MinLower: 2, MinUpper: 2, MinDigits: 2, MinSymbols: 2, NoAmbig: true, NoSeq: true, NoRepeat: true, SymbolSet: "!@#$%"}
p, err := generateOne(o)
if err != nil {
t.Fatal(err)
}
if len(p) != 20 {
t.Fatalf("length=%d", len(p))
}
var lo, up, di, sy int
for _, c := range p {
switch {
case strings.ContainsRune(lower, c):
lo++
case strings.ContainsRune(upper, c):
up++
case strings.ContainsRune(digits, c):
di++
default:
sy++
}
}
if lo < 2 || up < 2 || di < 2 || sy < 2 {
t.Fatalf("class minimums not met: %q", p)
}
}
func TestOneTimeClipDisappearsAfterReveal(t *testing.T) {
r := newRoom("test", 10)
c := &Clip{ID: "x", Room: "test", Content: "secret", Secret: true, OneTime: true, CreatedAt: time.Now().UTC()}
r.add(c)
if _, ok := r.reveal("x"); !ok {
t.Fatal("first reveal failed")
}
if _, ok := r.reveal("x"); ok {
t.Fatal("one-time clip still exists")
}
}
func TestExpiredClipIsPruned(t *testing.T) {
r := newRoom("test", 10)
exp := time.Now().UTC().Add(-time.Minute)
r.add(&Clip{ID: "old", Room: "test", Content: "x", ExpiresAt: &exp, CreatedAt: time.Now().UTC().Add(-time.Hour)})
if got := r.history(10); len(got) != 0 {
t.Fatalf("expected expired clip to be pruned, got %d", len(got))
}
}
func TestFilenameIsReducedToBase(t *testing.T) {
name, err := cleanOriginalName("../../payload.exe")
if err != nil {
t.Fatal(err)
}
if name != "payload.exe" {
t.Fatalf("unexpected name %q", name)
}
}
func TestIPv4PrefixLastAndMask(t *testing.T) {
p, err := netip.ParsePrefix("10.20.30.40/24")
if err != nil {
t.Fatal(err)
}
if got := prefixLast(p.Masked()).String(); got != "10.20.30.255" {
t.Fatalf("last=%s", got)
}
if got := prefixMask4(24); got != "255.255.255.0" {
t.Fatalf("mask=%s", got)
}
}
func TestParseSRVName(t *testing.T) {
svc, proto, name := parseSRVName("_ldap._tcp.example.local")
if svc != "ldap" || proto != "tcp" || name != "example.local" {
t.Fatalf("got %q %q %q", svc, proto, name)
}
}
func TestClipboardPersistsRoomsSecretsAndEmptyRooms(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "clipboard.json")
store := newClipboardStore(20, path, true)
if err := store.createRoom("alpha"); err != nil {
t.Fatal(err)
}
if err := store.createRoom("empty-room"); err != nil {
t.Fatal(err)
}
store.room("alpha").add(&Clip{ID: "normal", Room: "alpha", Type: "text", Content: "hello", CreatedAt: time.Now().UTC()})
store.room("alpha").add(&Clip{ID: "secret", Room: "alpha", Type: "password", Content: "P@ssw0rd!", Secret: true, CreatedAt: time.Now().UTC()})
if err := store.save(); err != nil {
t.Fatal(err)
}
reloaded := newClipboardStore(20, path, true)
if err := reloaded.load(); err != nil {
t.Fatal(err)
}
if _, ok := reloaded.getRoom("empty-room"); !ok {
t.Fatal("empty room was not persisted")
}
r, ok := reloaded.getRoom("alpha")
if !ok {
t.Fatal("alpha room missing after reload")
}
r.mu.RLock()
defer r.mu.RUnlock()
if len(r.clips) != 2 {
t.Fatalf("expected 2 clips after reload, got %d", len(r.clips))
}
if !r.clips[1].Secret || r.clips[1].Content != "P@ssw0rd!" {
t.Fatal("secret was not persisted correctly")
}
}
func TestClipboardClearKeepsRoomDeleteRemovesRoomPersistently(t *testing.T) {
dir := t.TempDir()
path := filepath.Join(dir, "clipboard.json")
store := newClipboardStore(20, path, true)
if err := store.createRoom("keep"); err != nil {
t.Fatal(err)
}
store.room("keep").add(&Clip{ID: "x", Room: "keep", Content: "value", CreatedAt: time.Now().UTC()})
if err := store.save(); err != nil {
t.Fatal(err)
}
if err := store.clearRoom("keep"); err != nil {
t.Fatal(err)
}
reloaded := newClipboardStore(20, path, true)
if err := reloaded.load(); err != nil {
t.Fatal(err)
}
r, ok := reloaded.getRoom("keep")
if !ok {
t.Fatal("cleared room should still exist")
}
if got := len(r.history(10)); got != 0 {
t.Fatalf("cleared room has %d clips", got)
}
if err := reloaded.deleteRoom("keep"); err != nil {
t.Fatal(err)
}
reloadedAgain := newClipboardStore(20, path, true)
if err := reloadedAgain.load(); err != nil {
t.Fatal(err)
}
if _, ok := reloadedAgain.getRoom("keep"); ok {
t.Fatal("deleted room reappeared after reload")
}
}
func TestFileStorePersistsMetadataAndBlob(t *testing.T) {
dir := t.TempDir()
store := newFileStore(dir, 1024*1024)
if err := os.MkdirAll(store.dir, 0o700); err != nil {
t.Fatal(err)
}
id := "persisted-file"
content := []byte("persistent file data")
if err := os.WriteFile(store.filePath(id), content, 0o600); err != nil {
t.Fatal(err)
}
store.files[id] = &FileMeta{ID: id, Name: "test.txt", Size: int64(len(content)), SHA256: "dummy", UploadedAt: time.Now().UTC()}
store.mu.Lock()
if err := store.saveLocked(); err != nil {
store.mu.Unlock()
t.Fatal(err)
}
store.mu.Unlock()
reloaded := newFileStore(dir, 1024*1024)
if err := reloaded.load(); err != nil {
t.Fatal(err)
}
files := reloaded.list()
if len(files) != 1 || files[0].ID != id {
t.Fatalf("file metadata not restored: %#v", files)
}
got, err := os.ReadFile(reloaded.filePath(id))
if err != nil {
t.Fatal(err)
}
if string(got) != string(content) {
t.Fatalf("blob changed: %q", got)
}
}