storj/cmd/uplink/cmd_ls_test.go
Jeff Wendling 89ccfe2dd7 cmd/uplink: fix recursive copy and improve tests
recursive copy had a bug with relative local paths.

this fixes that bug and changes the test framework
to use more of the code that actually runs in uplink
and only mocks out the direct interaction with the
operating system.

Change-Id: I9da2a80bfda8f86a8d05879b87171f299f759c7e
2022-05-11 15:17:16 -04:00

468 lines
16 KiB
Go

// Copyright (C) 2021 Storj Labs, Inc.
// See LICENSE for copying information.
package main
import (
"testing"
"storj.io/storj/cmd/uplink/ultest"
)
func TestLsErrors(t *testing.T) {
state := ultest.Setup(commands)
// empty bucket name is a parse error
state.Fail(t, "ls", "sj:///user")
}
func TestLsRemote(t *testing.T) {
state := ultest.Setup(commands,
ultest.WithFile("sj://user/deep/aaa/bbb/1"),
ultest.WithFile("sj://user/deep/aaa/bbb/2"),
ultest.WithFile("sj://user/deep/aaa/bbb/3"),
ultest.WithFile("sj://user/foobar"),
ultest.WithFile("sj://user/foobar/"),
ultest.WithFile("sj://user/foobar/1"),
ultest.WithFile("sj://user/foobar/2"),
ultest.WithFile("sj://user/foobar/3"),
ultest.WithFile("sj://user/foobaz/1"),
ultest.WithPendingFile("sj://user/invisible"),
)
t.Run("Recursive", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user", "--recursive", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:01 0 deep/aaa/bbb/1
OBJ 1970-01-01 00:00:02 0 deep/aaa/bbb/2
OBJ 1970-01-01 00:00:03 0 deep/aaa/bbb/3
OBJ 1970-01-01 00:00:04 0 foobar
OBJ 1970-01-01 00:00:05 0 foobar/
OBJ 1970-01-01 00:00:06 0 foobar/1
OBJ 1970-01-01 00:00:07 0 foobar/2
OBJ 1970-01-01 00:00:08 0 foobar/3
OBJ 1970-01-01 00:00:09 0 foobaz/1
`)
})
t.Run("Basic", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/fo", "--utc").RequireStdout(t, ``)
})
t.Run("ExactPrefix", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/foobar", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:04 0 foobar
PRE foobar/
`)
})
t.Run("ExactPrefixWithSlash", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/foobar/", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:05 0
OBJ 1970-01-01 00:00:06 0 1
OBJ 1970-01-01 00:00:07 0 2
OBJ 1970-01-01 00:00:08 0 3
`)
})
t.Run("MultipleLayers", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/deep/").RequireStdout(t, `
KIND CREATED SIZE KEY
PRE aaa/
`)
state.Succeed(t, "ls", "sj://user/deep/aaa/").RequireStdout(t, `
KIND CREATED SIZE KEY
PRE bbb/
`)
state.Succeed(t, "ls", "sj://user/deep/aaa/bbb/", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:01 0 1
OBJ 1970-01-01 00:00:02 0 2
OBJ 1970-01-01 00:00:03 0 3
`)
})
}
func TestLsJSON(t *testing.T) {
state := ultest.Setup(commands,
ultest.WithFile("sj://user/deep/aaa/bbb/1"),
ultest.WithFile("sj://user/deep/aaa/bbb/2"),
ultest.WithFile("sj://user/deep/aaa/bbb/3"),
ultest.WithFile("sj://user/foobar"),
ultest.WithFile("sj://user/foobar/"),
ultest.WithFile("sj://user/foobar/1"),
ultest.WithFile("sj://user/foobar/2"),
ultest.WithFile("sj://user/foobar/3"),
ultest.WithFile("sj://user/foobaz/1"),
ultest.WithPendingFile("sj://user/invisible"),
)
t.Run("Recursive", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user", "--recursive", "--utc", "--output", "json").RequireStdout(t, `
{"kind":"OBJ","created":"1970-01-01 00:00:01","size":0,"key":"deep/aaa/bbb/1"}
{"kind":"OBJ","created":"1970-01-01 00:00:02","size":0,"key":"deep/aaa/bbb/2"}
{"kind":"OBJ","created":"1970-01-01 00:00:03","size":0,"key":"deep/aaa/bbb/3"}
{"kind":"OBJ","created":"1970-01-01 00:00:04","size":0,"key":"foobar"}
{"kind":"OBJ","created":"1970-01-01 00:00:05","size":0,"key":"foobar/"}
{"kind":"OBJ","created":"1970-01-01 00:00:06","size":0,"key":"foobar/1"}
{"kind":"OBJ","created":"1970-01-01 00:00:07","size":0,"key":"foobar/2"}
{"kind":"OBJ","created":"1970-01-01 00:00:08","size":0,"key":"foobar/3"}
{"kind":"OBJ","created":"1970-01-01 00:00:09","size":0,"key":"foobaz/1"}
`)
})
t.Run("Basic", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/fo", "--utc", "--output", "json").RequireStdout(t, ``)
})
t.Run("ExactPrefix", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/foobar", "--utc", "--output", "json").RequireStdout(t, `
{"kind":"OBJ","created":"1970-01-01 00:00:04","size":0,"key":"foobar"}
{"kind":"PRE","key":"foobar/"}
`)
})
t.Run("ShortFlag", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/foobar", "--utc", "-o", "json").RequireStdout(t, `
{"kind":"OBJ","created":"1970-01-01 00:00:04","size":0,"key":"foobar"}
{"kind":"PRE","key":"foobar/"}
`)
})
t.Run("ExactPrefixWithSlash", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/foobar/", "--utc", "--output", "json").RequireStdout(t, `
{"kind":"OBJ","created":"1970-01-01 00:00:05","size":0,"key":""}
{"kind":"OBJ","created":"1970-01-01 00:00:06","size":0,"key":"1"}
{"kind":"OBJ","created":"1970-01-01 00:00:07","size":0,"key":"2"}
{"kind":"OBJ","created":"1970-01-01 00:00:08","size":0,"key":"3"}
`)
})
t.Run("MultipleLayers", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/deep/", "--output", "json").RequireStdout(t, `
{"kind":"PRE","key":"aaa/"}
`)
state.Succeed(t, "ls", "sj://user/deep/aaa/", "--output", "json").RequireStdout(t, `
{"kind":"PRE","key":"bbb/"}
`)
state.Succeed(t, "ls", "sj://user/deep/aaa/bbb/", "--utc", "--output", "json").RequireStdout(t, `
{"kind":"OBJ","created":"1970-01-01 00:00:01","size":0,"key":"1"}
{"kind":"OBJ","created":"1970-01-01 00:00:02","size":0,"key":"2"}
{"kind":"OBJ","created":"1970-01-01 00:00:03","size":0,"key":"3"}
`)
})
}
func TestLsPending(t *testing.T) {
state := ultest.Setup(commands,
ultest.WithPendingFile("sj://user/deep/aaa/bbb/1"),
ultest.WithPendingFile("sj://user/deep/aaa/bbb/2"),
ultest.WithPendingFile("sj://user/deep/aaa/bbb/3"),
ultest.WithPendingFile("sj://user/foobar"),
ultest.WithPendingFile("sj://user/foobar/"),
ultest.WithPendingFile("sj://user/foobar/1"),
ultest.WithPendingFile("sj://user/foobar/2"),
ultest.WithPendingFile("sj://user/foobar/3"),
ultest.WithPendingFile("sj://user/foobaz/1"),
ultest.WithFile("sj://user/invisible"),
)
t.Run("Recursive", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user", "--recursive", "--pending", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:01 0 deep/aaa/bbb/1
OBJ 1970-01-01 00:00:02 0 deep/aaa/bbb/2
OBJ 1970-01-01 00:00:03 0 deep/aaa/bbb/3
OBJ 1970-01-01 00:00:04 0 foobar
OBJ 1970-01-01 00:00:05 0 foobar/
OBJ 1970-01-01 00:00:06 0 foobar/1
OBJ 1970-01-01 00:00:07 0 foobar/2
OBJ 1970-01-01 00:00:08 0 foobar/3
OBJ 1970-01-01 00:00:09 0 foobaz/1
`)
})
t.Run("Basic", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/fo", "--pending", "--utc").RequireStdout(t, ``)
})
t.Run("ExactPrefix", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/foobar", "--pending", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:04 0 foobar
PRE foobar/
`)
})
t.Run("ExactPrefixWithSlash", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/foobar/", "--pending", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:05 0
OBJ 1970-01-01 00:00:06 0 1
OBJ 1970-01-01 00:00:07 0 2
OBJ 1970-01-01 00:00:08 0 3
`)
})
t.Run("MultipleLayers", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/deep/", "--pending").RequireStdout(t, `
KIND CREATED SIZE KEY
PRE aaa/
`)
state.Succeed(t, "ls", "sj://user/deep/aaa/", "--pending").RequireStdout(t, `
KIND CREATED SIZE KEY
PRE bbb/
`)
state.Succeed(t, "ls", "sj://user/deep/aaa/bbb/", "--pending", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:01 0 1
OBJ 1970-01-01 00:00:02 0 2
OBJ 1970-01-01 00:00:03 0 3
`)
})
}
func TestLsDifficult(t *testing.T) {
state := ultest.Setup(commands,
ultest.WithFile("sj://user//"),
ultest.WithFile("sj://user///"),
ultest.WithFile("sj://user////"),
ultest.WithFile("sj://user//starts-slash"),
ultest.WithFile("sj://user/ends-slash"),
ultest.WithFile("sj://user/ends-slash/"),
ultest.WithFile("sj://user/ends-slash//"),
ultest.WithFile("sj://user/mid-slash"),
ultest.WithFile("sj://user/mid-slash//2"),
ultest.WithFile("sj://user/mid-slash/1"),
)
t.Run("Recursive", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user", "--recursive", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:01 0 /
OBJ 1970-01-01 00:00:02 0 //
OBJ 1970-01-01 00:00:03 0 ///
OBJ 1970-01-01 00:00:04 0 /starts-slash
OBJ 1970-01-01 00:00:05 0 ends-slash
OBJ 1970-01-01 00:00:06 0 ends-slash/
OBJ 1970-01-01 00:00:07 0 ends-slash//
OBJ 1970-01-01 00:00:08 0 mid-slash
OBJ 1970-01-01 00:00:09 0 mid-slash//2
OBJ 1970-01-01 00:00:10 0 mid-slash/1
`)
})
t.Run("Basic", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
PRE /
OBJ 1970-01-01 00:00:05 0 ends-slash
PRE ends-slash/
OBJ 1970-01-01 00:00:08 0 mid-slash
PRE mid-slash/
`)
state.Succeed(t, "ls", "sj://user/", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
PRE /
OBJ 1970-01-01 00:00:05 0 ends-slash
PRE ends-slash/
OBJ 1970-01-01 00:00:08 0 mid-slash
PRE mid-slash/
`)
})
t.Run("OnlySlash", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user//", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:01 0
PRE /
OBJ 1970-01-01 00:00:04 0 starts-slash
`)
state.Succeed(t, "ls", "sj://user///", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:02 0
PRE /
`)
state.Succeed(t, "ls", "sj://user////", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:03 0
`)
})
t.Run("EndsSlash", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/ends-slash", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:05 0 ends-slash
PRE ends-slash/
`)
state.Succeed(t, "ls", "sj://user/ends-slash/", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:06 0
PRE /
`)
state.Succeed(t, "ls", "sj://user/ends-slash//", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:07 0
`)
})
t.Run("MidSlash", func(t *testing.T) {
state.Succeed(t, "ls", "sj://user/mid-slash", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:08 0 mid-slash
PRE mid-slash/
`)
state.Succeed(t, "ls", "sj://user/mid-slash/", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
PRE /
OBJ 1970-01-01 00:00:10 0 1
`)
state.Succeed(t, "ls", "sj://user/mid-slash//", "--utc").RequireStdout(t, `
KIND CREATED SIZE KEY
OBJ 1970-01-01 00:00:09 0 2
`)
})
}
func TestLsLocal(t *testing.T) {
state := ultest.Setup(commands,
ultest.WithFile("/user/deep/aaa/bbb/1"),
ultest.WithFile("/user/deep/aaa/bbb/2"),
ultest.WithFile("/user/deep/aaa/bbb/3"),
ultest.WithFile("/user/foobar/1"),
ultest.WithFile("/user/foobar/2"),
ultest.WithFile("/user/foobar/3"),
ultest.WithFile("/user/foobaz/1"),
)
t.Run("Recursive", func(t *testing.T) {
state.Succeed(t, "ls", "/user", "--recursive", "--utc").RequireStdoutGlob(t, `
KIND CREATED SIZE KEY
OBJ 20 /user/deep/aaa/bbb/1
OBJ 20 /user/deep/aaa/bbb/2
OBJ 20 /user/deep/aaa/bbb/3
OBJ 14 /user/foobar/1
OBJ 14 /user/foobar/2
OBJ 14 /user/foobar/3
OBJ 14 /user/foobaz/1
`)
})
t.Run("Basic", func(t *testing.T) {
state.Succeed(t, "ls", "/user/fo", "--utc").RequireStdout(t, ``)
})
t.Run("ExactPrefix", func(t *testing.T) {
state.Succeed(t, "ls", "/user/foobar", "--utc").RequireStdoutGlob(t, `
KIND CREATED SIZE KEY
OBJ 14 1
OBJ 14 2
OBJ 14 3
`)
})
t.Run("ExactPrefixWithSlash", func(t *testing.T) {
state.Succeed(t, "ls", "/user/foobar/", "--utc").RequireStdoutGlob(t, `
KIND CREATED SIZE KEY
OBJ 14 1
OBJ 14 2
OBJ 14 3
`)
})
t.Run("MultipleLayers", func(t *testing.T) {
state.Succeed(t, "ls", "/user/deep/").RequireStdout(t, `
KIND CREATED SIZE KEY
PRE aaa/
`)
state.Succeed(t, "ls", "/user/deep/aaa/").RequireStdout(t, `
KIND CREATED SIZE KEY
PRE bbb/
`)
state.Succeed(t, "ls", "/user/deep/aaa/bbb/", "--utc").RequireStdoutGlob(t, `
KIND CREATED SIZE KEY
OBJ 20 1
OBJ 20 2
OBJ 20 3
`)
})
}
func TestLsRelative(t *testing.T) {
state := ultest.Setup(commands,
ultest.WithFile("deep/aaa/bbb/1"),
ultest.WithFile("deep/aaa/bbb/2"),
ultest.WithFile("deep/aaa/bbb/3"),
ultest.WithFile("foobar/1"),
ultest.WithFile("foobar/2"),
ultest.WithFile("foobar/3"),
ultest.WithFile("foobaz/1"),
)
basic := `
KIND CREATED SIZE KEY
PRE deep/
PRE foobar/
PRE foobaz/
`
t.Run("Basic", func(t *testing.T) {
state.Succeed(t, "ls", "", "--utc").RequireStdout(t, basic)
})
t.Run("BasicDot", func(t *testing.T) {
state.Succeed(t, "ls", ".", "--utc").RequireStdout(t, basic)
})
t.Run("BasicDotSlash", func(t *testing.T) {
state.Succeed(t, "ls", "./", "--utc").RequireStdout(t, basic)
})
recursive := `
KIND CREATED SIZE KEY
OBJ 14 deep/aaa/bbb/1
OBJ 14 deep/aaa/bbb/2
OBJ 14 deep/aaa/bbb/3
OBJ 8 foobar/1
OBJ 8 foobar/2
OBJ 8 foobar/3
OBJ 8 foobaz/1
`
t.Run("Recursive", func(t *testing.T) {
state.Succeed(t, "ls", "", "--recursive", "--utc").RequireStdoutGlob(t, recursive)
})
t.Run("RecursiveDot", func(t *testing.T) {
state.Succeed(t, "ls", ".", "--recursive", "--utc").RequireStdoutGlob(t, recursive)
})
t.Run("RecursiveDotSlash", func(t *testing.T) {
state.Succeed(t, "ls", "./", "--recursive", "--utc").RequireStdoutGlob(t, recursive)
})
}