X-Git-Url: https://ruderich.org/simon/gitweb/?a=blobdiff_plain;f=main_test.go;h=8a1625887e746e4539b5279c16118f95823f8b49;hb=476239f9e6243f1949b7c81671e34823a2d0c193;hp=21dc0463958659df5151cf34edf29c82c26634ce;hpb=ba614f8f445aa5490484427ecb3f643345b69358;p=nsscash%2Fnsscash.git diff --git a/main_test.go b/main_test.go index 21dc046..8a16258 100644 --- a/main_test.go +++ b/main_test.go @@ -184,6 +184,20 @@ func TestMainFetch(t *testing.T) { defer log.SetOutput(os.Stderr) tests := []func(args){ + // Perform most tests with passwd for simplicity + fetchPasswdCacheFileDoesNotExist, + fetchPasswd404, + fetchPasswdEmpty, + fetchPasswdInvalid, + fetchPasswdLimits, + fetchPasswd, + // Tests for plain and group + fetchPlainEmpty, + fetchPlain, + fetchGroupEmpty, + fetchGroupInvalid, + fetchGroupLimits, + fetchGroup, // Special tests fetchNoConfig, } @@ -231,6 +245,355 @@ func TestMainFetch(t *testing.T) { } } +func fetchPasswdCacheFileDoesNotExist(a args) { + t := a.t + mustWritePasswdConfig(t, a.url) + + err := mainFetch(configPath) + mustBeErrorWithSubstring(t, err, + "file.path \""+passwdPath+"\" must exist") + + mustNotExist(t, statePath, passwdPath, plainPath, groupPath) +} + +func fetchPasswd404(a args) { + t := a.t + mustWritePasswdConfig(t, a.url) + mustCreate(t, passwdPath) + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + // 404 + w.WriteHeader(http.StatusNotFound) + } + + err := mainFetch(configPath) + mustBeErrorWithSubstring(t, err, + "status code 404") + + mustNotExist(t, statePath, plainPath, groupPath) + mustBeOld(a.t, passwdPath) +} + +func fetchPasswdEmpty(a args) { + t := a.t + mustWritePasswdConfig(t, a.url) + mustCreate(t, passwdPath) + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + // Empty response + } + + err := mainFetch(configPath) + mustBeErrorWithSubstring(t, err, + "refusing to use empty passwd file") + + mustNotExist(t, statePath, plainPath, groupPath) + mustBeOld(t, passwdPath) +} + +func fetchPasswdInvalid(a args) { + t := a.t + mustWritePasswdConfig(t, a.url) + mustCreate(t, passwdPath) + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/passwd" { + return + } + + fmt.Fprintln(w, "root:x:invalid:0:root:/root:/bin/bash") + } + + err := mainFetch(configPath) + mustBeErrorWithSubstring(t, err, + "invalid uid in line") + + mustNotExist(t, statePath, plainPath, groupPath) + mustBeOld(t, passwdPath) +} + +func fetchPasswdLimits(a args) { + t := a.t + mustWritePasswdConfig(t, a.url) + mustCreate(t, passwdPath) + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/passwd" { + return + } + + fmt.Fprint(w, "root:x:0:0:root:/root:/bin/bash") + for i := 0; i < 65536; i++ { + fmt.Fprint(w, "x") + } + fmt.Fprint(w, "\n") + } + + err := mainFetch(configPath) + mustBeErrorWithSubstring(t, err, + "passwd too large to serialize") + + mustNotExist(t, statePath, plainPath, groupPath) + mustBeOld(t, passwdPath) +} + +func fetchPasswd(a args) { + t := a.t + mustWritePasswdConfig(t, a.url) + mustCreate(t, passwdPath) + mustHaveHash(t, passwdPath, "da39a3ee5e6b4b0d3255bfef95601890afd80709") + + t.Log("First fetch, write files") + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/passwd" { + return + } + + // No "Last-Modified" header + fmt.Fprintln(w, "root:x:0:0:root:/root:/bin/bash") + fmt.Fprintln(w, "daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin") + } + + err := mainFetch(configPath) + if err != nil { + t.Error(err) + } + + mustNotExist(t, plainPath, groupPath) + mustBeNew(t, passwdPath, statePath) + // The actual content of passwdPath is verified by the NSS tests + mustHaveHash(t, passwdPath, "bbb7db67469b111200400e2470346d5515d64c23") + + t.Log("Fetch again, no support for Last-Modified") + + mustMakeOld(t, passwdPath, statePath) + + err = mainFetch(configPath) + if err != nil { + t.Error(err) + } + + mustNotExist(t, plainPath, groupPath) + mustBeNew(t, passwdPath, statePath) + mustHaveHash(t, passwdPath, "bbb7db67469b111200400e2470346d5515d64c23") + + t.Log("Fetch again, support for Last-Modified, but not retrieved yet") + + mustMakeOld(t, passwdPath, statePath) + + lastChange := time.Now() + *a.handler = func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/passwd" { + return + } + + modified := r.Header.Get("If-Modified-Since") + if modified != "" { + x, err := http.ParseTime(modified) + if err != nil { + t.Fatalf("invalid If-Modified-Since %v", + modified) + } + if !x.Before(lastChange) { + w.WriteHeader(http.StatusNotModified) + return + } + } + + w.Header().Add("Last-Modified", + lastChange.Format(http.TimeFormat)) + fmt.Fprintln(w, "root:x:0:0:root:/root:/bin/bash") + fmt.Fprintln(w, "daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin") + } + + err = mainFetch(configPath) + if err != nil { + t.Error(err) + } + + mustNotExist(t, plainPath, groupPath) + mustBeNew(t, passwdPath, statePath) + mustHaveHash(t, passwdPath, "bbb7db67469b111200400e2470346d5515d64c23") + + t.Log("Fetch again, support for Last-Modified") + + mustMakeOld(t, passwdPath, statePath) + + err = mainFetch(configPath) + if err != nil { + t.Error(err) + } + + mustNotExist(t, plainPath, groupPath) + mustBeOld(t, passwdPath) + mustBeNew(t, statePath) + mustHaveHash(t, passwdPath, "bbb7db67469b111200400e2470346d5515d64c23") + + t.Log("Corrupt local passwd cache, fetched again") + + os.Chmod(passwdPath, 0644) // make writable again + mustCreate(t, passwdPath) + mustMakeOld(t, passwdPath, statePath) + + err = mainFetch(configPath) + if err != nil { + t.Error(err) + } + + mustNotExist(t, plainPath, groupPath) + mustBeNew(t, passwdPath, statePath) + mustHaveHash(t, passwdPath, "bbb7db67469b111200400e2470346d5515d64c23") +} + +func fetchPlainEmpty(a args) { + t := a.t + mustWriteConfig(t, fmt.Sprintf(` +statepath = "%[1]s" + +[[file]] +type = "plain" +url = "%[2]s/plain" +path = "%[3]s" +`, statePath, a.url, plainPath)) + mustCreate(t, plainPath) + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + // Empty response + } + + err := mainFetch(configPath) + mustBeErrorWithSubstring(t, err, + "refusing to use empty response") + + mustNotExist(t, statePath, passwdPath, groupPath) + mustBeOld(t, plainPath) +} + +func fetchPlain(a args) { + t := a.t + mustWriteConfig(t, fmt.Sprintf(` +statepath = "%[1]s" + +[[file]] +type = "plain" +url = "%[2]s/plain" +path = "%[3]s" +`, statePath, a.url, plainPath)) + mustCreate(t, plainPath) + mustHaveHash(t, plainPath, "da39a3ee5e6b4b0d3255bfef95601890afd80709") + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/plain" { + return + } + + fmt.Fprintln(w, "some file") + } + + err := mainFetch(configPath) + if err != nil { + t.Error(err) + } + + mustNotExist(t, passwdPath, groupPath) + mustBeNew(t, plainPath, statePath) + mustHaveHash(t, plainPath, "0e08b5e8c10abc3e455b75286ba4a1fbd56e18a5") + + // Remaining functionality already tested in fetchPasswd() +} + +func fetchGroupEmpty(a args) { + t := a.t + mustWriteGroupConfig(t, a.url) + mustCreate(t, groupPath) + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + // Empty response + } + + err := mainFetch(configPath) + mustBeErrorWithSubstring(t, err, + "refusing to use empty group file") + + mustNotExist(t, statePath, passwdPath, plainPath) + mustBeOld(t, groupPath) +} + +func fetchGroupInvalid(a args) { + t := a.t + mustWriteGroupConfig(t, a.url) + mustCreate(t, groupPath) + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/group" { + return + } + + fmt.Fprintln(w, "root:x::") + } + + err := mainFetch(configPath) + mustBeErrorWithSubstring(t, err, + "invalid gid in line") + + mustNotExist(t, statePath, passwdPath, plainPath) + mustBeOld(t, groupPath) +} + +func fetchGroupLimits(a args) { + t := a.t + mustWriteGroupConfig(t, a.url) + mustCreate(t, groupPath) + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/group" { + return + } + + fmt.Fprint(w, "root:x:0:") + for i := 0; i < 65536; i++ { + fmt.Fprint(w, "x") + } + fmt.Fprint(w, "\n") + } + + err := mainFetch(configPath) + mustBeErrorWithSubstring(t, err, + "group too large to serialize") + + mustNotExist(t, statePath, passwdPath, plainPath) + mustBeOld(t, groupPath) +} + +func fetchGroup(a args) { + t := a.t + mustWriteGroupConfig(t, a.url) + mustCreate(t, groupPath) + mustHaveHash(t, groupPath, "da39a3ee5e6b4b0d3255bfef95601890afd80709") + + *a.handler = func(w http.ResponseWriter, r *http.Request) { + if r.URL.Path != "/group" { + return + } + + fmt.Fprintln(w, "root:x:0:") + fmt.Fprintln(w, "daemon:x:1:andariel,duriel,mephisto,diablo,baal") + } + + err := mainFetch(configPath) + if err != nil { + t.Error(err) + } + + mustNotExist(t, passwdPath, plainPath) + mustBeNew(t, groupPath, statePath) + // The actual content of groupPath is verified by the NSS tests + mustHaveHash(t, groupPath, "8c27a8403278ba2e392b86d98d4dff1fdefcafdd") + + // Remaining functionality already tested in fetchPasswd() +} + func fetchNoConfig(a args) { t := a.t