| 1 | package main |
| 2 | |
| 3 | import ( |
| 4 | "errors" |
| 5 | "testing" |
| 6 | ) |
| 7 | |
| 8 | func TestLocalTimezone(t *testing.T) { |
| 9 | noLink := func(string) (string, error) { return "", errors.New("no") } |
| 10 | noFile := func(string) ([]byte, error) { return nil, errors.New("no") } |
| 11 | env := func(v string) func(string) string { |
| 12 | return func(k string) string { |
| 13 | if k == "TZ" { |
| 14 | return v |
| 15 | } |
| 16 | return "" |
| 17 | } |
| 18 | } |
| 19 | link := func(target string) func(string) (string, error) { |
| 20 | return func(string) (string, error) { return target, nil } |
| 21 | } |
| 22 | file := func(body string) func(string) ([]byte, error) { |
| 23 | return func(string) ([]byte, error) { return []byte(body), nil } |
| 24 | } |
| 25 | cases := []struct { |
| 26 | name string |
| 27 | getenv func(string) string |
| 28 | readlink func(string) (string, error) |
| 29 | readFile func(string) ([]byte, error) |
| 30 | want string |
| 31 | }{ |
| 32 | {"TZ plain", env("Europe/London"), noLink, noFile, "Europe/London"}, |
| 33 | {"TZ colon", env(":Europe/London"), noLink, noFile, "Europe/London"}, |
| 34 | {"TZ path", env("/usr/share/zoneinfo/Asia/Kolkata"), noLink, noFile, "Asia/Kolkata"}, |
| 35 | {"localtime link (linux)", env(""), func(string) (string, error) { return "/usr/share/zoneinfo/Europe/Dublin", nil }, noFile, "Europe/Dublin"}, |
| 36 | {"localtime link (macOS)", env(""), func(string) (string, error) { return "/var/db/timezone/zoneinfo/Australia/Sydney", nil }, noFile, "Australia/Sydney"}, |
| 37 | {"etc/timezone", env(""), noLink, func(string) ([]byte, error) { return []byte("Europe/Paris\n"), nil }, "Europe/Paris"}, |
| 38 | // Review Focus 1: real-machine noise is a clean name or nothing. |
| 39 | {"etc/timezone padded", env(""), noLink, func(string) ([]byte, error) { return []byte(" America/New_York \r\n# trailing\n"), nil }, "America/New_York"}, |
| 40 | {"TZ bare colon", env(":"), noLink, noFile, ""}, |
| 41 | {"TZ localtime", env("localtime"), noLink, noFile, ""}, |
| 42 | {"TZ posixrules path", env("/usr/share/zoneinfo/posixrules"), noLink, noFile, ""}, |
| 43 | {"TZ POSIX rule string", env("EST5EDT,M3.2.0,M11.1.0"), noLink, noFile, ""}, |
| 44 | {"nothing", env(""), noLink, noFile, ""}, |
| 45 | // Source order and fall-through: more than one source is live. |
| 46 | {"TZ beats link", env("Europe/London"), link("/usr/share/zoneinfo/Asia/Tokyo"), noFile, "Europe/London"}, |
| 47 | {"invalid TZ falls through to link", env("EST5EDT,M3.2.0,M11.1.0"), link("/usr/share/zoneinfo/Asia/Tokyo"), noFile, "Asia/Tokyo"}, |
| 48 | {"link beats etc/timezone", env(""), link("/usr/share/zoneinfo/Asia/Tokyo"), file("Europe/Paris\n"), "Asia/Tokyo"}, |
| 49 | {"invalid link falls through to etc/timezone", env(""), link("/usr/share/zoneinfo/posixrules"), file("Europe/Paris\n"), "Europe/Paris"}, |
| 50 | } |
| 51 | for _, c := range cases { |
| 52 | if got := localTimezone(c.getenv, c.readlink, c.readFile); got != c.want { |
| 53 | t.Errorf("%s: %q, want %q", c.name, got, c.want) |
| 54 | } |
| 55 | } |
| 56 | } |
| 57 | |