Read misc.territory, timezone, useragent and car as tables, and state the data rules behind them #23
@@ -352,8 +352,8 @@ func TestRunSelectsATableRow(t *testing.T) {
|
||||
if code, _, errb := runOut("--no-shipped-data", "-d", dir, "[Skåne län]"); code != 2 || !strings.Contains(errb, "JSON") {
|
||||
t.Fatalf("[Skåne län] = %d, stderr=%q, want misuse: a leading bracket that is no JSON names nothing", code, errb)
|
||||
}
|
||||
if code, out, _ := runOut("--seed", "1", "--format", "csv", "misc.country[SE]"); code != 0 || !strings.HasPrefix(out, "alpha2,") || !strings.Contains(out, "\nSE,SWE,") {
|
||||
t.Fatalf("--format csv misc.country[SE] = %d, %q", code, out)
|
||||
if code, out, _ := runOut("--seed", "1", "--format", "csv", "misc.territory[SE]"); code != 0 || !strings.HasPrefix(out, "alpha2,") || !strings.Contains(out, "\nSE,SWE,") {
|
||||
t.Fatalf("--format csv misc.territory[SE] = %d, %q", code, out)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+18
-17
@@ -95,23 +95,24 @@ func TestShippedMiscCategories(t *testing.T) {
|
||||
func TestShippedMiscReferenceData(t *testing.T) {
|
||||
f := newGenerator(t, "data/misc", WithSeed(1))
|
||||
re := map[string]*regexp.Regexp{
|
||||
"currency": regexp.MustCompile(`^[A-Z]{3}$`),
|
||||
"currency.name": regexp.MustCompile(`\p{L}`),
|
||||
"currency.symbol": regexp.MustCompile(`^\S+$`),
|
||||
"country": regexp.MustCompile(`\p{L}`),
|
||||
"country.alpha2": regexp.MustCompile(`^[A-Z]{2}$`),
|
||||
"country.alpha3": regexp.MustCompile(`^[A-Z]{3}$`),
|
||||
"language": regexp.MustCompile(`\p{L}`),
|
||||
"language.code": regexp.MustCompile(`^[a-z]{2}$`),
|
||||
"language.code3": regexp.MustCompile(`^[a-z]{3}$`),
|
||||
"timezone": regexp.MustCompile(`^([A-Za-z_]+(/[A-Za-z_]+)+|UTC)$`),
|
||||
"mimetype": regexp.MustCompile(`^[a-z]+/[a-z0-9.+-]+$`),
|
||||
"mimetype.ext": regexp.MustCompile(`^\.[a-z0-9_-]+$`),
|
||||
"httpstatus": regexp.MustCompile(`^[1-5]\d{2} \S.*$`),
|
||||
"httpstatus.code": regexp.MustCompile(`^[1-5]\d{2}$`),
|
||||
"useragent": regexp.MustCompile(`^Mozilla/5\.0 .+`),
|
||||
"car": regexp.MustCompile(`^\S.* \S`),
|
||||
"car.maker": regexp.MustCompile(`^\S`),
|
||||
"currency": regexp.MustCompile(`^[A-Z]{3}$`),
|
||||
"currency.name": regexp.MustCompile(`\p{L}`),
|
||||
"currency.symbol": regexp.MustCompile(`^\S+$`),
|
||||
"territory": regexp.MustCompile(`\p{L}`),
|
||||
"territory.alpha2": regexp.MustCompile(`^[A-Z]{2}$`),
|
||||
"territory.alpha3": regexp.MustCompile(`^[A-Z]{3}$`),
|
||||
"territory.country": regexp.MustCompile(`^[A-Z]{2}$`),
|
||||
"language": regexp.MustCompile(`\p{L}`),
|
||||
"language.code": regexp.MustCompile(`^[a-z]{2}$`),
|
||||
"language.code3": regexp.MustCompile(`^[a-z]{3}$`),
|
||||
"timezone": regexp.MustCompile(`^([A-Za-z_]+(/[A-Za-z_]+)+|UTC)$`),
|
||||
"mimetype": regexp.MustCompile(`^[a-z]+/[a-z0-9.+-]+$`),
|
||||
"mimetype.ext": regexp.MustCompile(`^\.[a-z0-9_-]+$`),
|
||||
"httpstatus": regexp.MustCompile(`^[1-5]\d{2} \S.*$`),
|
||||
"httpstatus.code": regexp.MustCompile(`^[1-5]\d{2}$`),
|
||||
"useragent": regexp.MustCompile(`^Mozilla/5\.0 .+`),
|
||||
"car": regexp.MustCompile(`^\S.* \S`),
|
||||
"car.maker": regexp.MustCompile(`^\S`),
|
||||
}
|
||||
for i := 0; i < 100; i++ {
|
||||
for p, rx := range re {
|
||||
|
||||
+3
-3
@@ -108,9 +108,9 @@ func TestFakeTemplateErrors(t *testing.T) {
|
||||
{`name: {/no.such.path}`, "no entry"},
|
||||
{`name: {..nope}`, "write {/nope}"},
|
||||
{`{"format":"x"}`, "is a string"},
|
||||
{`{/misc.country} {/misc.country.alpha2}`, "renders a level that {/misc.country.alpha2} reads a path into; name the fields you want instead, or draw them apart with a drawGroup"},
|
||||
{`{"format":"{/misc.country.alpha2} {x}","x":"{/misc.country}"}`, "reads a path into"},
|
||||
{`{"format":"{/misc.country.alpha2}","drawGroup":"g"}`, "nothing can reference"},
|
||||
{`{/misc.territory} {/misc.territory.alpha2}`, "renders a level that {/misc.territory.alpha2} reads a path into; name the fields you want instead, or draw them apart with a drawGroup"},
|
||||
{`{"format":"{/misc.territory.alpha2} {x}","x":"{/misc.territory}"}`, "reads a path into"},
|
||||
{`{"format":"{/misc.territory.alpha2}","drawGroup":"g"}`, "nothing can reference"},
|
||||
} {
|
||||
_, err := f.FakeTemplate(c.input)
|
||||
if err == nil || !strings.Contains(err.Error(), c.want) {
|
||||
|
||||
+1
-1
@@ -154,7 +154,7 @@ func TestListedPathsAllRender(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, p := range []string{"misc.car.maker", "misc.country.alpha2", "misc.country.numeric", "misc.currency.symbol", "misc.httpstatus.code", "misc.mimetype.ext"} {
|
||||
for _, p := range []string{"misc.car.maker", "misc.territory.alpha2", "misc.territory.numeric", "misc.currency.symbol", "misc.httpstatus.code", "misc.mimetype.ext"} {
|
||||
if !slices.Contains(paths, p) {
|
||||
t.Errorf("List() omits %q, which the README advertises and Fake renders", p)
|
||||
}
|
||||
|
||||
+74
-45
@@ -644,17 +644,17 @@ func TestTableRowsAreAlternatives(t *testing.T) {
|
||||
|
||||
func TestTableOverridesByLayering(t *testing.T) {
|
||||
mine := writeFiles(t, map[string]string{
|
||||
"misc/country.json": `{"format":"{name}","rows":"country.tsv","key":"alpha2"}`,
|
||||
"misc/country.tsv": "alpha2\tname\nXX\tNowhere\nYY\tElsewhere\n",
|
||||
"misc/territory.json": `{"format":"{name}","rows":"territory.tsv","key":"alpha2"}`,
|
||||
"misc/territory.tsv": "alpha2\tname\nXX\tNowhere\nYY\tElsewhere\n",
|
||||
})
|
||||
f, err := New(WithDataPath(mine), WithSeed(1))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if v := fake(t, f, "misc.country[XX]"); v != "Nowhere" {
|
||||
t.Fatalf("misc.country[XX] = %q, want the layered table", v)
|
||||
if v := fake(t, f, "misc.territory[XX]"); v != "Nowhere" {
|
||||
t.Fatalf("misc.territory[XX] = %q, want the layered table", v)
|
||||
}
|
||||
if paths := f.List(); slices.Contains(paths, "misc.country.alpha3") {
|
||||
if paths := f.List(); slices.Contains(paths, "misc.territory.alpha3") {
|
||||
t.Fatal("List() still offers the shipped table's columns under an overridden category")
|
||||
}
|
||||
}
|
||||
@@ -662,50 +662,55 @@ func TestTableOverridesByLayering(t *testing.T) {
|
||||
func TestShippedTables(t *testing.T) {
|
||||
f := newGenerator(t, "data/misc", WithSeed(1))
|
||||
for path, want := range map[string]string{
|
||||
"country[SE]": "Sweden",
|
||||
"country[Sweden].alpha3": "SWE",
|
||||
"country[SE].numeric": "752",
|
||||
"country[SE].tld": ".se",
|
||||
"country[SE].calling-code": "46",
|
||||
"country[SE].capital": "Stockholm",
|
||||
"country[SE].currency": "SEK",
|
||||
"country[SE].flag": "🇸🇪",
|
||||
"currency[SEK].name": "Swedish Krona",
|
||||
"currency[SEK].symbol": "kr",
|
||||
"currency[SEK].numeric": "752",
|
||||
"currency[SEK].decimals": "2",
|
||||
"currency[Euro].code": "EUR",
|
||||
"language[sv]": "Swedish",
|
||||
"language[sv].code3": "swe",
|
||||
"language[Swedish].code": "sv",
|
||||
"language[nl]": "Dutch",
|
||||
"httpstatus[200]": "200 OK",
|
||||
"httpstatus[404]": "404 Not Found",
|
||||
"httpstatus[404].reason": "Not Found",
|
||||
"httpstatus[451].reason": "Unavailable For Legal Reasons",
|
||||
"httpstatus[500].reason": "Internal Server Error",
|
||||
"mimetype[application/json].ext": ".json",
|
||||
"mimetype[text/markdown].ext": ".md",
|
||||
"mimetype[.jpg]": "image/jpeg",
|
||||
"mimetype[.mov]": "video/quicktime",
|
||||
"mimetype[.mp3]": "audio/mpeg",
|
||||
"mimetype[.mp4]": "video/mp4",
|
||||
"mimetype[.ogg]": "audio/ogg",
|
||||
"territory[SE]": "Sweden",
|
||||
"territory[Sweden].alpha3": "SWE",
|
||||
"territory[SE].numeric": "752",
|
||||
"territory[SE].tld": ".se",
|
||||
"territory[SE].calling-code": "46",
|
||||
"territory[SE].capital": "Stockholm",
|
||||
"territory[SE].currency": "SEK",
|
||||
"territory[SE].flag": "🇸🇪",
|
||||
"territory[SE].country": "SE",
|
||||
"territory[GL]": "Greenland",
|
||||
"territory[GL].country": "DK",
|
||||
"territory[Åland Islands].country": "FI",
|
||||
"currency[SEK].name": "Swedish Krona",
|
||||
"currency[SEK].symbol": "kr",
|
||||
"currency[SEK].numeric": "752",
|
||||
"currency[SEK].decimals": "2",
|
||||
"currency[Euro].code": "EUR",
|
||||
"language[sv]": "Swedish",
|
||||
"language[sv].code3": "swe",
|
||||
"language[Swedish].code": "sv",
|
||||
"language[nl]": "Dutch",
|
||||
"httpstatus[200]": "200 OK",
|
||||
"httpstatus[404]": "404 Not Found",
|
||||
"httpstatus[404].reason": "Not Found",
|
||||
"httpstatus[451].reason": "Unavailable For Legal Reasons",
|
||||
"httpstatus[500].reason": "Internal Server Error",
|
||||
"mimetype[application/json].ext": ".json",
|
||||
"mimetype[text/markdown].ext": ".md",
|
||||
"mimetype[.jpg]": "image/jpeg",
|
||||
"mimetype[.mov]": "video/quicktime",
|
||||
"mimetype[.mp3]": "audio/mpeg",
|
||||
"mimetype[.mp4]": "video/mp4",
|
||||
"mimetype[.ogg]": "audio/ogg",
|
||||
} {
|
||||
if got := fake(t, f, path); got != want {
|
||||
t.Errorf("Fake(%q) = %q, want %q", path, got, want)
|
||||
}
|
||||
}
|
||||
re := map[string]*regexp.Regexp{
|
||||
"country.numeric": regexp.MustCompile(`^\d{3}$`),
|
||||
"country.tld": regexp.MustCompile(`^\.[a-z]{2}$`),
|
||||
"country.calling-code": regexp.MustCompile(`^\d{1,4}(-\d{3})?$`),
|
||||
"country.capital": regexp.MustCompile(`\p{L}`),
|
||||
"country.currency": regexp.MustCompile(`^[A-Z]{3}$`),
|
||||
"country.flag": regexp.MustCompile(`^[\x{1F1E6}-\x{1F1FF}]{2}$`),
|
||||
"country.languages": regexp.MustCompile(`^[a-z]{2,3}(-[A-Z]{2})?(,[a-z]{2,3}(-[A-Z]{2})?)*$`),
|
||||
"currency.numeric": regexp.MustCompile(`^\d{3}$`),
|
||||
"currency.decimals": regexp.MustCompile(`^[0-4]$`),
|
||||
"territory.numeric": regexp.MustCompile(`^\d{3}$`),
|
||||
"territory.tld": regexp.MustCompile(`^\.[a-z]{2}$`),
|
||||
"territory.calling-code": regexp.MustCompile(`^\d{1,4}(-\d{3})?$`),
|
||||
"territory.capital": regexp.MustCompile(`\p{L}`),
|
||||
"territory.country": regexp.MustCompile(`^[A-Z]{2}$`),
|
||||
"territory.currency": regexp.MustCompile(`^[A-Z]{3}$`),
|
||||
"territory.flag": regexp.MustCompile(`^[\x{1F1E6}-\x{1F1FF}]{2}$`),
|
||||
"territory.languages": regexp.MustCompile(`^[a-z]{2,3}(-[A-Z]{2})?(,[a-z]{2,3}(-[A-Z]{2})?)*$`),
|
||||
"currency.numeric": regexp.MustCompile(`^\d{3}$`),
|
||||
"currency.decimals": regexp.MustCompile(`^[0-4]$`),
|
||||
}
|
||||
for i := 0; i < 100; i++ {
|
||||
for p, rx := range re {
|
||||
@@ -716,10 +721,34 @@ func TestShippedTables(t *testing.T) {
|
||||
}
|
||||
count := map[string]bool{}
|
||||
for i := 0; i < 5000; i++ {
|
||||
count[fake(t, f, "country.alpha2")] = true
|
||||
count[fake(t, f, "territory.alpha2")] = true
|
||||
}
|
||||
if len(count) < 200 {
|
||||
t.Fatalf("country draws %d distinct rows in 5000, want the full register", len(count))
|
||||
t.Fatalf("territory draws %d distinct rows in 5000, want the full register", len(count))
|
||||
}
|
||||
}
|
||||
|
||||
// TestEveryTerritoryNamesAShippedCountry proves what no parent can: the sovereign a
|
||||
// territory names is a row of the same table, which a link would make a cycle.
|
||||
func TestEveryTerritoryNamesAShippedCountry(t *testing.T) {
|
||||
data, err := os.ReadFile(filepath.Join("data", "misc", "territory.tsv"))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
lines := strings.Split(strings.TrimSuffix(string(data), "\n"), "\n")
|
||||
head := strings.Split(lines[0], "\t")
|
||||
alpha2, country := slices.Index(head, "alpha2"), slices.Index(head, "country")
|
||||
if alpha2 < 0 || country < 0 {
|
||||
t.Fatalf("territory.tsv columns %v, want alpha2 and country", head)
|
||||
}
|
||||
keys := map[string]bool{}
|
||||
for _, line := range lines[1:] {
|
||||
keys[strings.Split(line, "\t")[alpha2]] = true
|
||||
}
|
||||
for i, line := range lines[1:] {
|
||||
if c := strings.Split(line, "\t")[country]; !keys[c] {
|
||||
t.Errorf("territory.tsv line %d: country %q is no alpha2 of the table", i+2, c)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user