jsoncodec_test.go raw

   1  package nostr
   2  
   3  import (
   4  	"strings"
   5  	"testing"
   6  )
   7  
   8  func TestEmptyObjectKeyIsRejectedNotPanicked(t *testing.T) {
   9  	cases := []string{
  10  		`{"":1}`,
  11  		`{"id":"","":2}`,
  12  		`{"kinds":[1],"":null}`,
  13  	}
  14  	for _, raw := range cases {
  15  		if _, err := ParseEvent([]byte(raw)); err == nil {
  16  			t.Errorf("event %s accepted", raw)
  17  		}
  18  		if _, err := ParseFilter([]byte(raw)); err == nil {
  19  			t.Errorf("filter %s accepted", raw)
  20  		}
  21  	}
  22  	// A nested empty key in an unknown field must be skipped, not panic.
  23  	if _, err := ParseEvent([]byte(`{"unknown":{"":1}}`)); err == nil {
  24  		t.Fatal("expected missing-field error, got nil (but no panic)")
  25  	}
  26  }
  27  
  28  func TestEmptyKeyExtractID(t *testing.T) {
  29  	raw := `{"":1,"id":"eaeb41f2e1d44abc3949052406db478aeed872a64e46022daace5955cd65b316"}`
  30  	if got := ExtractID([]byte(raw)); got != "eaeb41f2e1d44abc3949052406db478aeed872a64e46022daace5955cd65b316" {
  31  		t.Fatalf("ExtractID = %q", got)
  32  	}
  33  	if got := ExtractID([]byte(`{"":1}`)); got != "" {
  34  		t.Fatalf("ExtractID on empty key = %q", got)
  35  	}
  36  }
  37  
  38  func TestSurrogateBounds(t *testing.T) {
  39  	if _, err := ParseJSONString([]byte(`"\uD800\u"`)); err == nil {
  40  		t.Fatal("truncated surrogate accepted")
  41  	}
  42  	if _, err := ParseJSONString([]byte(`"\uD800`)); err == nil {
  43  		t.Fatal("truncated escape accepted")
  44  	}
  45  	if _, err := ParseJSONString([]byte(`"\uDC00"`)); err == nil {
  46  		t.Fatal("lone low surrogate accepted")
  47  	}
  48  	got, err := ParseJSONString([]byte(`"\uD83D\uDE80"`))
  49  	if err != nil || got != "🚀" {
  50  		t.Fatalf("valid pair: %q %v", got, err)
  51  	}
  52  }
  53  
  54  func TestSplitArray(t *testing.T) {
  55  	parts, err := SplitArray([]byte(`["REQ","s",{"kinds":[1],"#e":["x"]}]`))
  56  	if err != nil || len(parts) != 3 {
  57  		t.Fatalf("parts=%q err=%v", parts, err)
  58  	}
  59  	if string(parts[0]) != `"REQ"` || string(parts[1]) != `"s"` {
  60  		t.Fatalf("parts: %q", parts)
  61  	}
  62  	f, err := ParseFilter(parts[2])
  63  	if err != nil || len(f.Kinds) != 1 || len(f.Tags["e"]) != 1 {
  64  		t.Fatalf("filter: %+v %v", f, err)
  65  	}
  66  	if _, err := SplitArray([]byte(`["EVENT",{"":1}]`)); err != nil {
  67  		t.Fatalf("split: %v", err)
  68  	}
  69  }
  70  
  71  func TestCodecRejectsMalformed(t *testing.T) {
  72  	cases := []string{
  73  		`{`,
  74  		`{"id":1}`,
  75  		`{"id":"zz"}`,
  76  		`{"kinds":[1.5]}`,
  77  		`{"kinds":[-1]}`,
  78  		`{"limit":1e3}`,
  79  		`{"#e":"x"}`,
  80  		`{"tags":[["e",1]]}`,
  81  		`{"content":"\q"}`,
  82  	}
  83  	for _, raw := range cases {
  84  		key := "event"
  85  		if strings.HasPrefix(raw, `{"kinds`) || strings.HasPrefix(raw, `{"#`) || strings.HasPrefix(raw, `{"limit`) {
  86  			key = "filter"
  87  		}
  88  		if key == "event" {
  89  			f := &Filter{}
  90  			_ = f
  91  			if _, err := ParseEvent([]byte(raw)); err == nil {
  92  				t.Errorf("event %s accepted", raw)
  93  			}
  94  		} else {
  95  			if _, err := ParseFilter([]byte(raw)); err == nil {
  96  				t.Errorf("filter %s accepted", raw)
  97  			}
  98  		}
  99  	}
 100  }
 101  
 102  func TestParseEventRoundTrip(t *testing.T) {
 103  	var sk [32]byte
 104  	sk[31] = 3
 105  	ev := &Event{Kind: 1, CreatedAt: 1700000000, Tags: Tags{{"t", "json"}}, Content: "hello \"json\"\n"}
 106  	if err := ev.Sign(sk); err != nil {
 107  		t.Fatal(err)
 108  	}
 109  	got, err := ParseEvent(ev.AppendJSON(nil))
 110  	if err != nil {
 111  		t.Fatal(err)
 112  	}
 113  	if got.ID != ev.ID || got.Content != ev.Content || len(got.Tags) != 1 {
 114  		t.Fatalf("round trip: %+v", got)
 115  	}
 116  }
 117