package fiesta import ( "encoding/json" "io/fs" "os" "strconv" "testing" ) // TestSourcesIsSourcesJSON: Sources() is hack/seed/sources.json, key // for key and field for field. The file is read from disk here, not // through the embed, so the test compares the API with the record // rather than with itself; a field the record has and Source lacks // fails by name, as does a key either side lacks. func TestSourcesIsSourcesJSON(t *testing.T) { b, err := os.ReadFile("hack/seed/sources.json") if err != nil { t.Fatal(err) } var record map[string]map[string]json.RawMessage if err := json.Unmarshal(b, &record); err != nil { t.Fatalf("hack/seed/sources.json: %v", err) } got := Sources() if len(record) < 160 { t.Fatalf("hack/seed/sources.json holds %d example states, want the seeded 160 or more; the comparison would be over too little", len(record)) } for _, key := range sortedNames(record) { source, ok := got[key] if !ok { t.Errorf("Sources() has no %s, which sources.json records", key) continue } fields := map[string]string{ "kind": strconv.Quote(source.Kind), "source": strconv.Quote(source.Source), "locale": strconv.Quote(source.Locale), "state": strconv.Itoa(source.State), } if source.View != "" { fields["view"] = strconv.Quote(source.View) } for _, field := range sortedNames(record[key]) { if want := string(record[key][field]); fields[field] != want { t.Errorf("Sources()[%q] has %s %s, and sources.json %s", key, field, fields[field], want) } } for field := range fields { if _, ok := record[key][field]; !ok { t.Errorf("Sources()[%q] has a %s, and sources.json none", key, field) } } } for _, key := range sortedNames(got) { if _, ok := record[key]; !ok { t.Errorf("Sources() has %s, which sources.json does not record", key) } } } // TestEverySourceIsAnExampleState: each key Sources() returns is an // example and one of its states, as examples/examples.json lists them, // so a caller can open the example a source names. func TestEverySourceIsAnExampleState(t *testing.T) { var manifest struct { Examples []struct { Name string States []struct{ ID string } } } b, err := fs.ReadFile(FS(), "examples/examples.json") if err != nil { t.Fatal(err) } if err := json.Unmarshal(b, &manifest); err != nil { t.Fatal(err) } states := map[string]bool{} for _, example := range manifest.Examples { for _, state := range example.States { states[example.Name+"/"+state.ID] = true } } for _, key := range sortedNames(Sources()) { if !states[key] { t.Errorf("Sources() has %s, which is no example state in examples/examples.json", key) } } } // TestSourcesIsACopy: a caller that edits the map it was given does not // edit the next caller's. func TestSourcesIsACopy(t *testing.T) { first := Sources() for key := range first { delete(first, key) } if len(Sources()) == 0 { t.Error("emptying the map Sources() returned emptied the next call's") } }