store_interface_test.go raw

   1  package store
   2  
   3  import (
   4  	"bytes"
   5  	"testing"
   6  
   7  	ntypes "next.orly.dev/pkg/nostr/types"
   8  )
   9  
  10  func TestNewIdPkTs(t *testing.T) {
  11  	// Create sample data
  12  	id := make([]byte, 32)
  13  	pub := make([]byte, 32)
  14  	for i := 0; i < 32; i++ {
  15  		id[i] = byte(i)
  16  		pub[i] = byte(i + 32)
  17  	}
  18  
  19  	ipk := NewIdPkTs(id, pub, 1234567890, 42)
  20  
  21  	// Test that data was copied correctly
  22  	if !bytes.Equal(ipk.Id[:], id) {
  23  		t.Errorf("Id: got %x, want %x", ipk.Id[:], id)
  24  	}
  25  	if !bytes.Equal(ipk.Pub[:], pub) {
  26  		t.Errorf("Pub: got %x, want %x", ipk.Pub[:], pub)
  27  	}
  28  	if ipk.Ts != 1234567890 {
  29  		t.Errorf("Ts: got %d, want 1234567890", ipk.Ts)
  30  	}
  31  	if ipk.Ser != 42 {
  32  		t.Errorf("Ser: got %d, want 42", ipk.Ser)
  33  	}
  34  
  35  	// Test that Id is a copy (modifying original doesn't affect struct)
  36  	id[0] = 0xFF
  37  	if ipk.Id[0] == 0xFF {
  38  		t.Error("NewIdPkTs should copy data, not reference")
  39  	}
  40  }
  41  
  42  func TestIdPkTsSliceMethods(t *testing.T) {
  43  	id := make([]byte, 32)
  44  	pub := make([]byte, 32)
  45  	for i := 0; i < 32; i++ {
  46  		id[i] = byte(i)
  47  		pub[i] = byte(i + 32)
  48  	}
  49  
  50  	ipk := NewIdPkTs(id, pub, 1234567890, 42)
  51  
  52  	// Test IDSlice returns correct data
  53  	idSlice := ipk.IDSlice()
  54  	if !bytes.Equal(idSlice, id) {
  55  		t.Errorf("IDSlice: got %x, want %x", idSlice, id)
  56  	}
  57  
  58  	// Test PubSlice returns correct data
  59  	pubSlice := ipk.PubSlice()
  60  	if !bytes.Equal(pubSlice, pub) {
  61  		t.Errorf("PubSlice: got %x, want %x", pubSlice, pub)
  62  	}
  63  
  64  	// Test hex methods
  65  	idHex := ipk.IDHex()
  66  	expectedIDHex := "000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f"
  67  	if idHex != expectedIDHex {
  68  		t.Errorf("IDHex: got %s, want %s", idHex, expectedIDHex)
  69  	}
  70  }
  71  
  72  func TestIdPkTsCopyOnAssignment(t *testing.T) {
  73  	id := make([]byte, 32)
  74  	pub := make([]byte, 32)
  75  	for i := 0; i < 32; i++ {
  76  		id[i] = byte(i)
  77  		pub[i] = byte(i + 32)
  78  	}
  79  
  80  	ipk1 := NewIdPkTs(id, pub, 1234567890, 42)
  81  	ipk2 := ipk1 // Copy
  82  
  83  	// Modify the copy
  84  	ipk2.Id[0] = 0xFF
  85  
  86  	// Original should be unchanged (arrays are copied on assignment)
  87  	if ipk1.Id[0] == 0xFF {
  88  		t.Error("IdPkTs should copy on assignment")
  89  	}
  90  }
  91  
  92  func TestEventRef(t *testing.T) {
  93  	id := make([]byte, 32)
  94  	pub := make([]byte, 32)
  95  	for i := 0; i < 32; i++ {
  96  		id[i] = byte(i)
  97  		pub[i] = byte(i + 100)
  98  	}
  99  
 100  	// Create EventRef
 101  	ref := NewEventRef(id, pub, 1234567890, 42)
 102  
 103  	// Test accessors - need to get addressable values for slicing
 104  	refID := ref.ID()
 105  	refPub := ref.Pub()
 106  	if !bytes.Equal(refID[:], id) {
 107  		t.Error("ID() mismatch")
 108  	}
 109  	if !bytes.Equal(refPub[:], pub) {
 110  		t.Error("Pub() mismatch")
 111  	}
 112  	if ref.Ts() != 1234567890 {
 113  		t.Error("Ts() mismatch")
 114  	}
 115  	if ref.Ser() != 42 {
 116  		t.Error("Ser() mismatch")
 117  	}
 118  
 119  	// Test copy-on-assignment
 120  	ref2 := ref
 121  	testID := ref.ID()
 122  	testID[0] = 0xFF
 123  	ref2ID := ref2.ID()
 124  	if ref2ID[0] == 0xFF {
 125  		t.Error("EventRef should copy on assignment")
 126  	}
 127  
 128  	// Test hex methods
 129  	if len(ref.IDHex()) != 64 {
 130  		t.Errorf("IDHex length: got %d, want 64", len(ref.IDHex()))
 131  	}
 132  }
 133  
 134  func TestEventRefToIdPkTs(t *testing.T) {
 135  	id := make([]byte, 32)
 136  	pub := make([]byte, 32)
 137  	for i := 0; i < 32; i++ {
 138  		id[i] = byte(i)
 139  		pub[i] = byte(i + 100)
 140  	}
 141  
 142  	ref := NewEventRef(id, pub, 1234567890, 42)
 143  	ipk := ref.ToIdPkTs()
 144  
 145  	// Verify conversion
 146  	if !bytes.Equal(ipk.Id[:], id) {
 147  		t.Error("ToIdPkTs: Id mismatch")
 148  	}
 149  	if !bytes.Equal(ipk.Pub[:], pub) {
 150  		t.Error("ToIdPkTs: Pub mismatch")
 151  	}
 152  	if ipk.Ts != 1234567890 {
 153  		t.Error("ToIdPkTs: Ts mismatch")
 154  	}
 155  	if ipk.Ser != 42 {
 156  		t.Error("ToIdPkTs: Ser mismatch")
 157  	}
 158  
 159  	// Verify independence (modifications don't affect original)
 160  	ipk.Id[0] = 0xFF
 161  	if ref.ID()[0] == 0xFF {
 162  		t.Error("ToIdPkTs should create independent copy")
 163  	}
 164  }
 165  
 166  func TestIdPkTsToEventRef(t *testing.T) {
 167  	id := make([]byte, 32)
 168  	pub := make([]byte, 32)
 169  	for i := 0; i < 32; i++ {
 170  		id[i] = byte(i)
 171  		pub[i] = byte(i + 100)
 172  	}
 173  
 174  	ipk := NewIdPkTs(id, pub, 1234567890, 42)
 175  	ref := ipk.ToEventRef()
 176  
 177  	// Verify conversion - need addressable values for slicing
 178  	refID := ref.ID()
 179  	refPub := ref.Pub()
 180  	if !bytes.Equal(refID[:], id) {
 181  		t.Error("ToEventRef: ID mismatch")
 182  	}
 183  	if !bytes.Equal(refPub[:], pub) {
 184  		t.Error("ToEventRef: Pub mismatch")
 185  	}
 186  	if ref.Ts() != 1234567890 {
 187  		t.Error("ToEventRef: Ts mismatch")
 188  	}
 189  	if ref.Ser() != 42 {
 190  		t.Error("ToEventRef: Ser mismatch")
 191  	}
 192  }
 193  
 194  func BenchmarkIdPkTsCopy(b *testing.B) {
 195  	id := make([]byte, 32)
 196  	pub := make([]byte, 32)
 197  	for i := 0; i < 32; i++ {
 198  		id[i] = byte(i)
 199  		pub[i] = byte(i + 100)
 200  	}
 201  
 202  	ipk := NewIdPkTs(id, pub, 1234567890, 42)
 203  
 204  	b.ResetTimer()
 205  	for i := 0; i < b.N; i++ {
 206  		ipk2 := ipk // Copy (should stay on stack)
 207  		_ = ipk2
 208  	}
 209  }
 210  
 211  func BenchmarkEventRefCopy(b *testing.B) {
 212  	id := make([]byte, 32)
 213  	pub := make([]byte, 32)
 214  	for i := 0; i < 32; i++ {
 215  		id[i] = byte(i)
 216  		pub[i] = byte(i + 100)
 217  	}
 218  
 219  	ref := NewEventRef(id, pub, 1234567890, 42)
 220  
 221  	b.ResetTimer()
 222  	for i := 0; i < b.N; i++ {
 223  		ref2 := ref // Copy (should stay on stack)
 224  		_ = ref2
 225  	}
 226  }
 227  
 228  func BenchmarkIdPkTsToEventRef(b *testing.B) {
 229  	id := make([]byte, 32)
 230  	pub := make([]byte, 32)
 231  	for i := 0; i < 32; i++ {
 232  		id[i] = byte(i)
 233  		pub[i] = byte(i + 100)
 234  	}
 235  
 236  	ipk := NewIdPkTs(id, pub, 1234567890, 42)
 237  
 238  	b.ResetTimer()
 239  	for i := 0; i < b.N; i++ {
 240  		ref := ipk.ToEventRef()
 241  		_ = ref
 242  	}
 243  }
 244  
 245  func BenchmarkEventRefAccess(b *testing.B) {
 246  	id := make([]byte, 32)
 247  	pub := make([]byte, 32)
 248  	for i := 0; i < 32; i++ {
 249  		id[i] = byte(i)
 250  		pub[i] = byte(i + 100)
 251  	}
 252  
 253  	ref := NewEventRef(id, pub, 1234567890, 42)
 254  
 255  	b.ResetTimer()
 256  	for i := 0; i < b.N; i++ {
 257  		idCopy := ref.ID()
 258  		pubCopy := ref.Pub()
 259  		_ = idCopy
 260  		_ = pubCopy
 261  	}
 262  }
 263  
 264  func BenchmarkIdPkTsAccess(b *testing.B) {
 265  	id := make([]byte, 32)
 266  	pub := make([]byte, 32)
 267  	for i := 0; i < 32; i++ {
 268  		id[i] = byte(i)
 269  		pub[i] = byte(i + 100)
 270  	}
 271  
 272  	ipk := NewIdPkTs(id, pub, 1234567890, 42)
 273  
 274  	b.ResetTimer()
 275  	for i := 0; i < b.N; i++ {
 276  		idCopy := ipk.Id
 277  		pubCopy := ipk.Pub
 278  		_ = idCopy
 279  		_ = pubCopy
 280  	}
 281  }
 282  
 283  // Ensure types satisfy expected size for stack allocation
 284  func TestStructSizes(t *testing.T) {
 285  	var ipk IdPkTs
 286  	var ref EventRef
 287  
 288  	// Both should be exactly 80 bytes (32+32+8+8)
 289  	// This is not directly testable in Go, but we can verify the fields exist
 290  	_ = ipk.Id
 291  	_ = ipk.Pub
 292  	_ = ipk.Ts
 293  	_ = ipk.Ser
 294  	_ = ref
 295  }
 296  
 297  // Ensure ntypes.EventID and ntypes.Pubkey are used correctly
 298  func TestNtypesCompatibility(t *testing.T) {
 299  	var id ntypes.EventID
 300  	var pub ntypes.Pubkey
 301  
 302  	// Fill with test data
 303  	for i := 0; i < 32; i++ {
 304  		id[i] = byte(i)
 305  		pub[i] = byte(i + 32)
 306  	}
 307  
 308  	// Create IdPkTs directly with ntypes
 309  	ipk := IdPkTs{
 310  		Id:  id,
 311  		Pub: pub,
 312  		Ts:  1234567890,
 313  		Ser: 42,
 314  	}
 315  
 316  	// Verify
 317  	if ipk.Id != id {
 318  		t.Error("ntypes.EventID should be directly assignable to IdPkTs.Id")
 319  	}
 320  	if ipk.Pub != pub {
 321  		t.Error("ntypes.Pubkey should be directly assignable to IdPkTs.Pub")
 322  	}
 323  }
 324