Fixed time.Parse in runLs tests
Fixed runLs tests on Windows
diff --git a/server_stubs.go b/server_stubs.go
index 3699e90..41d5051 100644
--- a/server_stubs.go
+++ b/server_stubs.go
@@ -4,13 +4,15 @@
import (
"os"
+ "time"
+ "fmt"
)
func runLs(dirname string, dirent os.FileInfo) string {
typeword := runLsTypeWord(dirent)
numLinks := 1
- username := ""
- groupname := ""
+ username := "-"
+ groupname := "-"
mtime := dirent.ModTime()
monthStr := mtime.Month().String()[0:3]
day := mtime.Day()
diff --git a/server_test.go b/server_test.go
index 60643c1..87e4022 100644
--- a/server_test.go
+++ b/server_test.go
@@ -1,12 +1,12 @@
package sftp
import (
- "io"
- "sync"
"testing"
"os"
"regexp"
"time"
+ "io"
+ "sync"
)
const (
@@ -14,6 +14,143 @@
TYPE_FILE = "[^d]"
)
+func TestRunLsWithExamplesDirectory(t *testing.T) {
+ path := "examples"
+ item,_ := os.Stat(path)
+ result := runLs(path, item)
+ runLsTestHelper(t, result, TYPE_DIRECTORY, path)
+}
+
+
+func TestRunLsWithLicensesFile(t *testing.T) {
+ path := "LICENSE"
+ item,_ := os.Stat(path)
+ result := runLs(path, item)
+ runLsTestHelper(t, result, TYPE_FILE, path)
+}
+
+/*
+ The format of the `longname' field is unspecified by this protocol.
+ It MUST be suitable for use in the output of a directory listing
+ command (in fact, the recommended operation for a directory listing
+ command is to simply display this data). However, clients SHOULD NOT
+ attempt to parse the longname field for file attributes; they SHOULD
+ use the attrs field instead.
+
+ The recommended format for the longname field is as follows:
+
+ -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer
+ 1234567890 123 12345678 12345678 12345678 123456789012
+
+ Here, the first line is sample output, and the second field indicates
+ widths of the various fields. Fields are separated by spaces. The
+ first field lists file permissions for user, group, and others; the
+ second field is link count; the third field is the name of the user
+ who owns the file; the fourth field is the name of the group that
+ owns the file; the fifth field is the size of the file in bytes; the
+ sixth field (which actually may contain spaces, but is fixed to 12
+ characters) is the file modification time, and the seventh field is
+ the file name. Each field is specified to be a minimum of certain
+ number of character positions (indicated by the second line above),
+ but may also be longer if the data does not fit in the specified
+ length.
+
+ The SSH_FXP_ATTRS response has the following format:
+
+ uint32 id
+ ATTRS attrs
+
+ where `id' is the request identifier, and `attrs' is the returned
+ file attributes as described in Section ``File Attributes''.
+ */
+func runLsTestHelper(t *testing.T, result, expectedType, path string) {
+ // using regular expressions to make tests work on all systems
+ // a virtual file system (like afero) would be needed to mock valid filesystem checks
+ // expected layout is:
+ // drwxr-xr-x 8 501 20 272 Aug 9 19:46 examples
+
+ // permissions (len 10, "drwxr-xr-x")
+ got := result[0:10]
+ if ok, err := regexp.MatchString("^" + expectedType + "[rwx-]{9}$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): permission field mismatch, expected dir, got: %#v, err: %#v", path, got, err)
+ }
+
+ // space
+ got = result[10:11]
+ if ok, err := regexp.MatchString("^\\s$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): spacer 1 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
+ }
+
+ // link count (len 3, number)
+ got = result[12:15]
+ if ok, err := regexp.MatchString("^\\s*[0-9]+$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): link count field mismatch, got: %#v, err: %#v", path, got, err)
+ }
+
+ // spacer
+ got = result[15:16]
+ if ok, err := regexp.MatchString("^\\s$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): spacer 2 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
+ }
+
+ // username / uid (len 8, number or string)
+ got = result[16:24]
+ if ok, err := regexp.MatchString("^[^\\s]{1,8}\\s*$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): username / uid mismatch, expected user, got: %#v, err: %#v", path, got, err)
+ }
+
+ // spacer
+ got = result[24:25]
+ if ok, err := regexp.MatchString("^\\s$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): spacer 3 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
+ }
+
+ // groupname / gid (len 8, number or string)
+ got = result[25:33]
+ if ok, err := regexp.MatchString("^[^\\s]{1,8}\\s*$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): groupname / gid mismatch, expected group, got: %#v, err: %#v", path, got, err)
+ }
+
+
+ // spacer
+ got = result[33:34]
+ if ok, err := regexp.MatchString("^\\s$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): spacer 4 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
+ }
+
+ // filesize (len 8)
+ got = result[34:42]
+ if ok, err := regexp.MatchString("^\\s*[0-9]+$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): filesize field mismatch, expected size in bytes, got: %#v, err: %#v", path, got, err)
+ }
+
+ // spacer
+ got = result[42:43]
+ if ok, err := regexp.MatchString("^\\s$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): spacer 5 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
+ }
+
+ // mod time (len 12, e.g. Aug 9 19:46)
+ got = result[43:55]
+ layout := "Jan 2 15:04"
+ _, err := time.Parse(layout, got)
+ if err != nil {
+ t.Errorf("runLs(%#v, *FileInfo): mod time field mismatch, expected date layout %s, got: %#v, err: %#v", path, layout, got, err)
+ }
+
+ // spacer
+ got = result[55:56]
+ if ok, err := regexp.MatchString("^\\s$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): spacer 6 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
+ }
+
+ // filename
+ got = result[56:]
+ if ok, err := regexp.MatchString("^"+path+"$", got); !ok {
+ t.Errorf("runLs(%#v, *FileInfo): name field mismatch, expected examples, got: %#v, err: %#v", path, got, err)
+ }
+}
+
func clientServerPair(t *testing.T) (*Client, *Server) {
cr, sw := io.Pipe()
sr, cw := io.Pipe()
@@ -101,144 +238,3 @@
}
wg.Wait()
}
-
-
-
-
-func TestRunLsWithExamplesDirectory(t *testing.T) {
- path := "examples"
- item,_ := os.Stat(path)
- result := runLs(path, item)
- runLsTestHelper(t, result, TYPE_DIRECTORY, path)
-}
-
-
-func TestRunLsWithLicensesFile(t *testing.T) {
- path := "LICENSE"
- item,_ := os.Stat(path)
- result := runLs(path, item)
- runLsTestHelper(t, result, TYPE_FILE, path)
-}
-
-/*
- The format of the `longname' field is unspecified by this protocol.
- It MUST be suitable for use in the output of a directory listing
- command (in fact, the recommended operation for a directory listing
- command is to simply display this data). However, clients SHOULD NOT
- attempt to parse the longname field for file attributes; they SHOULD
- use the attrs field instead.
-
- The recommended format for the longname field is as follows:
-
- -rwxr-xr-x 1 mjos staff 348911 Mar 25 14:29 t-filexfer
- 1234567890 123 12345678 12345678 12345678 123456789012
-
- Here, the first line is sample output, and the second field indicates
- widths of the various fields. Fields are separated by spaces. The
- first field lists file permissions for user, group, and others; the
- second field is link count; the third field is the name of the user
- who owns the file; the fourth field is the name of the group that
- owns the file; the fifth field is the size of the file in bytes; the
- sixth field (which actually may contain spaces, but is fixed to 12
- characters) is the file modification time, and the seventh field is
- the file name. Each field is specified to be a minimum of certain
- number of character positions (indicated by the second line above),
- but may also be longer if the data does not fit in the specified
- length.
-
- The SSH_FXP_ATTRS response has the following format:
-
- uint32 id
- ATTRS attrs
-
- where `id' is the request identifier, and `attrs' is the returned
- file attributes as described in Section ``File Attributes''.
- */
-func runLsTestHelper(t *testing.T, result, expectedType, path string) {
- // using regular expressions to make tests work on all systems
- // a virtual file system (like afero) would be needed to mock valid filesystem checks
- // expected layout is:
- // drwxr-xr-x 8 501 20 272 Aug 9 19:46 examples
-
-
- // permissions (len 10, "drwxr-xr-x")
- got := result[0:10]
- if ok, err := regexp.MatchString("^" + expectedType + "[rwx-]{9}$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): permission field mismatch, expected dir, got: %#v, err: %#v", path, got, err)
- }
-
- // space
- got = result[10:11]
- if ok, err := regexp.MatchString("^\\s$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): spacer 1 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
- }
-
- // link count (len 3, number)
- got = result[12:15]
- if ok, err := regexp.MatchString("^\\s*[0-9]+$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): link count field mismatch, got: %#v, err: %#v", path, got, err)
- }
-
- // spacer
- got = result[15:16]
- if ok, err := regexp.MatchString("^\\s$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): spacer 2 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
- }
-
- // username / uid (len 8, number or string)
- got = result[16:24]
- if ok, err := regexp.MatchString("^[^\\s]{1,8}\\s*$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): username / uid mismatch, expected user, got: %#v, err: %#v", path, got, err)
- }
-
- // spacer
- got = result[24:25]
- if ok, err := regexp.MatchString("^\\s$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): spacer 3 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
- }
-
- // groupname / gid (len 8, number or string)
- got = result[25:33]
- if ok, err := regexp.MatchString("^[^\\s]{1,8}\\s*$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): groupname / gid mismatch, expected group, got: %#v, err: %#v", path, got, err)
- }
-
-
- // spacer
- got = result[33:34]
- if ok, err := regexp.MatchString("^\\s$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): spacer 4 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
- }
-
- // filesize (len 8)
- got = result[34:42]
- if ok, err := regexp.MatchString("^\\s*[0-9]+$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): filesize field mismatch, expected size in bytes, got: %#v, err: %#v", path, got, err)
- }
-
- // spacer
- got = result[42:43]
- if ok, err := regexp.MatchString("^\\s$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): spacer 5 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
- }
-
- // mod time (len 12, e.g. Aug 9 19:46)
- got = result[43:55]
- layout := "Jan 1 15:04"
- _, err := time.Parse(layout, got)
- if err != nil {
- t.Errorf("runLs(%#v, *FileInfo): mod time field mismatch, expected date layout %s, got: %#v, err: %#v", path, layout, got, err)
- }
-
- // spacer
- got = result[55:56]
- if ok, err := regexp.MatchString("^\\s$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): spacer 6 mismatch, expected whitespace, got: %#v, err: %#v", path, got, err)
- }
-
- // filename
- got = result[56:]
- if ok, err := regexp.MatchString("^"+path+"$", got); !ok {
- t.Errorf("runLs(%#v, *FileInfo): name field mismatch, expected examples, got: %#v, err: %#v", path, got, err)
- }
-}
\ No newline at end of file