Files
dokku/plugins/common/common_test.go
Jose Diaz-Gonzalez dbac12e9f1 refactor: route bash app name validation through go
The bash and go validators previously each kept their own copy of the regex, which had to be updated in lockstep. Both bash wrappers now invoke the existing common binary via the same pattern as `verify_app_name`, leaving go as the single source of truth. The legacy `IsValidAppNameOld` rule is also widened to allow underscores again so apps created under the old naming rules can still be looked up through `VerifyAppName`'s either-rule fallback.
2026-05-09 16:00:51 -04:00

280 lines
7.0 KiB
Go

package common
import (
"os"
"strings"
"testing"
. "github.com/onsi/gomega"
)
var (
testAppName = "test-app-1"
testAppDir = strings.Join([]string{"/home/dokku/", testAppName}, "")
testEnvFile = strings.Join([]string{testAppDir, "/ENV"}, "")
testEnvLine = "export testKey=TESTING"
testAppName2 = "01-test-app-1"
testAppDir2 = strings.Join([]string{"/home/dokku/", testAppName2}, "")
testEnvFile2 = strings.Join([]string{testAppDir2, "/ENV"}, "")
testEnvLine2 = "export testKey=TESTING"
)
func setupTests() (err error) {
if err := os.Setenv("PLUGIN_PATH", "/var/lib/dokku/plugins"); err != nil {
return err
}
return os.Setenv("PLUGIN_ENABLED_PATH", "/var/lib/dokku/plugins/enabled")
}
func setupTestApp() (err error) {
Expect(os.MkdirAll(testAppDir, 0766)).To(Succeed())
b := []byte(testEnvLine + "\n")
if err = os.WriteFile(testEnvFile, b, 0644); err != nil {
return
}
return
}
func setupTestApp2() (err error) {
Expect(os.MkdirAll(testAppDir2, 0766)).To(Succeed())
b := []byte(testEnvLine2 + "\n")
if err = os.WriteFile(testEnvFile2, b, 0644); err != nil {
return
}
return
}
func teardownTestApp() {
os.RemoveAll(testAppDir)
}
func teardownTestApp2() {
os.RemoveAll(testAppDir2)
}
func TestCommonGetEnv(t *testing.T) {
RegisterTestingT(t)
Expect(setupTests()).To(Succeed())
Expect(MustGetEnv("DOKKU_ROOT")).To(Equal("/home/dokku"))
}
func TestCommonGetAppImageRepo(t *testing.T) {
RegisterTestingT(t)
Expect(setupTests()).To(Succeed())
Expect(GetAppImageRepo("testapp")).To(Equal("dokku/testapp"))
}
func TestCommonVerifyImageInvalid(t *testing.T) {
RegisterTestingT(t)
Expect(setupTests()).To(Succeed())
Expect(VerifyImage("testapp")).To(Equal(false))
}
func TestCommonVerifyAppNameInvalid(t *testing.T) {
RegisterTestingT(t)
Expect(setupTests()).To(Succeed())
Expect(VerifyAppName("1994testApp")).To(HaveOccurred())
}
func TestCommonIsValidAppName(t *testing.T) {
RegisterTestingT(t)
validNames := []string{
"myapp",
"my-app",
"my.app",
"app123",
"123app",
"my-app.prod",
"a",
"0",
}
for _, name := range validNames {
Expect(IsValidAppName(name)).To(Succeed(), "expected %q to be a valid app name", name)
}
}
func TestCommonIsValidAppNameOld(t *testing.T) {
RegisterTestingT(t)
validNames := []string{
"myapp",
"my-app",
"my.app",
"my_app",
"legacy_app_name",
"app_v2",
}
for _, name := range validNames {
Expect(IsValidAppNameOld(name)).To(Succeed(), "expected %q to be a valid app name", name)
}
invalidNames := []string{
"app;id",
"app$cmd",
"app|cat",
"app/cmd",
"app:cmd",
"App",
"-app",
"_app",
"",
}
for _, name := range invalidNames {
Expect(IsValidAppNameOld(name)).To(HaveOccurred(), "expected %q to be rejected", name)
}
}
func TestCommonIsValidAppNameRejectsShellMetacharacters(t *testing.T) {
RegisterTestingT(t)
invalidNames := []string{
"app;id",
"app$cmd",
"app`whoami`",
"app|cat",
"app&background",
"app>file",
"app<file",
"app(cmd)",
"app{cmd}",
"app[cmd]",
"app*",
"app?",
"app!",
"app#",
"app\\cmd",
"app\"quote",
"app'quote",
"app cmd",
"app\tcmd",
"app\ncmd",
"app~cmd",
"app/cmd",
"app:cmd",
"app_name",
"App",
"-app",
".app",
"",
}
for _, name := range invalidNames {
Expect(IsValidAppName(name)).To(HaveOccurred(), "expected %q to be rejected", name)
}
}
func TestCommonVerifyAppName(t *testing.T) {
RegisterTestingT(t)
Expect(setupTests()).To(Succeed())
Expect(setupTestApp()).To(Succeed())
Expect(VerifyAppName(testAppName)).To(Succeed())
teardownTestApp()
RegisterTestingT(t)
Expect(setupTests()).To(Succeed())
Expect(setupTestApp2()).To(Succeed())
Expect(VerifyAppName(testAppName2)).To(Succeed())
teardownTestApp2()
}
func TestCommonDokkuAppsError(t *testing.T) {
RegisterTestingT(t)
Expect(setupTests()).To(Succeed())
_, err := DokkuApps()
Expect(err).To(HaveOccurred())
}
func TestCommonDokkuApps(t *testing.T) {
RegisterTestingT(t)
Expect(setupTests()).To(Succeed())
Expect(setupTestApp()).To(Succeed())
apps, err := DokkuApps()
Expect(err).NotTo(HaveOccurred())
Expect(apps).To(HaveLen(1))
Expect(apps[0]).To(Equal(testAppName))
teardownTestApp()
}
func TestCommonStripInlineComments(t *testing.T) {
RegisterTestingT(t)
Expect(setupTests()).To(Succeed())
text := StripInlineComments(strings.Join([]string{testEnvLine, "# testing comment"}, " "))
Expect(text).To(Equal(testEnvLine))
}
func TestParseReportArgsEmpty(t *testing.T) {
RegisterTestingT(t)
args, err := ParseReportArgs("scheduler", []string{})
Expect(err).NotTo(HaveOccurred())
Expect(args.IsGlobal).To(BeFalse())
Expect(args.InfoFlag).To(Equal(""))
Expect(args.OSArgs).To(BeEmpty())
}
func TestParseReportArgsAppOnly(t *testing.T) {
RegisterTestingT(t)
args, err := ParseReportArgs("scheduler", []string{"myapp"})
Expect(err).NotTo(HaveOccurred())
Expect(args.IsGlobal).To(BeFalse())
Expect(args.InfoFlag).To(Equal(""))
Expect(args.OSArgs).To(Equal([]string{"myapp"}))
}
func TestParseReportArgsFormatJSON(t *testing.T) {
RegisterTestingT(t)
args, err := ParseReportArgs("scheduler", []string{"myapp", "--format", "json"})
Expect(err).NotTo(HaveOccurred())
Expect(args.IsGlobal).To(BeFalse())
Expect(args.InfoFlag).To(Equal(""))
Expect(args.OSArgs).To(Equal([]string{"myapp", "--format", "json"}))
}
func TestParseReportArgsGlobalAlone(t *testing.T) {
RegisterTestingT(t)
args, err := ParseReportArgs("scheduler", []string{"--global"})
Expect(err).NotTo(HaveOccurred())
Expect(args.IsGlobal).To(BeTrue())
Expect(args.InfoFlag).To(Equal(""))
Expect(args.OSArgs).To(BeEmpty())
}
func TestParseReportArgsGlobalWithFormat(t *testing.T) {
RegisterTestingT(t)
args, err := ParseReportArgs("scheduler", []string{"--global", "--format", "json"})
Expect(err).NotTo(HaveOccurred())
Expect(args.IsGlobal).To(BeTrue())
Expect(args.InfoFlag).To(Equal(""))
Expect(args.OSArgs).To(Equal([]string{"--format", "json"}))
}
func TestParseReportArgsInfoFlag(t *testing.T) {
RegisterTestingT(t)
args, err := ParseReportArgs("scheduler", []string{"myapp", "--scheduler-selected"})
Expect(err).NotTo(HaveOccurred())
Expect(args.IsGlobal).To(BeFalse())
Expect(args.InfoFlag).To(Equal("--scheduler-selected"))
Expect(args.OSArgs).To(Equal([]string{"myapp"}))
}
func TestParseReportArgsAppThenGlobal(t *testing.T) {
RegisterTestingT(t)
args, err := ParseReportArgs("scheduler", []string{"myapp", "--global"})
Expect(err).NotTo(HaveOccurred())
Expect(args.IsGlobal).To(BeTrue())
Expect(args.InfoFlag).To(Equal(""))
Expect(args.OSArgs).To(Equal([]string{"myapp"}))
}
func TestParseReportArgsGlobalWithInfoFlag(t *testing.T) {
RegisterTestingT(t)
args, err := ParseReportArgs("scheduler", []string{"--global", "--scheduler-global-selected"})
Expect(err).NotTo(HaveOccurred())
Expect(args.IsGlobal).To(BeTrue())
Expect(args.InfoFlag).To(Equal("--scheduler-global-selected"))
Expect(args.OSArgs).To(BeEmpty())
}
func TestParseReportArgsMultipleInfoFlags(t *testing.T) {
RegisterTestingT(t)
_, err := ParseReportArgs("scheduler", []string{"--scheduler-selected", "--scheduler-global-selected"})
Expect(err).To(HaveOccurred())
}