Files
go-omni/cmd/go-omni/apigen/upgrade_test.go

168 lines
5.2 KiB
Go

package apigen
import (
"encoding/json"
"git.yuntuo.hk/k2safe/go-omni/cmd/go-omni/scaffold"
"go/format"
"os"
"path/filepath"
"strings"
"testing"
)
func oldInfrastructureProject(t *testing.T) string {
t.Helper()
dir := filepath.Join(t.TempDir(), "app")
if _, err := New(Options{Dir: dir, Module: "example.com/upgrade", FrameworkDir: frameworkRoot(t)}); err != nil {
t.Fatal(err)
}
previous, err := scaffold.LegacyAPIInfrastructure("example.com/upgrade", "none", "none", "stderr", "json")
if err != nil {
t.Fatal(err)
}
for name, content := range previous {
if strings.HasSuffix(name, ".go") {
content, err = format.Source(content)
if err != nil {
t.Fatal(err)
}
}
writeFile(t, filepath.Join(dir, name), string(content))
}
var m manifest
if err = json.Unmarshal([]byte(readFile(t, filepath.Join(dir, manifestPath))), &m); err != nil {
t.Fatal(err)
}
delete(m.Generated, "internal/svc/runtimeGen.go")
m.TemplateVersion = ""
_ = os.Remove(filepath.Join(dir, "internal/svc/runtimeGen.go"))
raw, _ := json.Marshal(m)
writeFile(t, filepath.Join(dir, manifestPath), string(raw))
path := filepath.Join(dir, "go.mod")
writeFile(t, path, strings.ReplaceAll(readFile(t, path), minimumVersion, "v0.13.0-preview"))
return dir
}
func TestUpgradeRejectsEscapingEntry(t *testing.T) {
dir := oldInfrastructureProject(t)
var m manifest
if err := json.Unmarshal([]byte(readFile(t, filepath.Join(dir, manifestPath))), &m); err != nil {
t.Fatal(err)
}
m.Entry = "../outside.api"
raw, _ := json.Marshal(m)
writeFile(t, filepath.Join(dir, manifestPath), string(raw))
before := snapshot(t, dir)
if _, err := ApplyUpgrade(dir); err == nil {
t.Fatal("escaping API entry accepted")
}
if !sameFiles(before, snapshot(t, dir)) {
t.Fatal("invalid upgrade wrote project")
}
}
func TestUpgradeV014PreservesExtensions(t *testing.T) {
dir := filepath.Join(t.TempDir(), "service")
if _, err := New(Options{Dir: dir, Module: "example.com/upgrade", FrameworkDir: frameworkRoot(t)}); err != nil {
t.Fatal(err)
}
var m manifest
if err := json.Unmarshal([]byte(readFile(t, filepath.Join(dir, manifestPath))), &m); err != nil {
t.Fatal(err)
}
m.TemplateVersion = "v0.14.0-preview"
raw, _ := json.Marshal(m)
writeFile(t, filepath.Join(dir, manifestPath), string(raw))
mod := filepath.Join(dir, "go.mod")
writeFile(t, mod, strings.ReplaceAll(readFile(t, mod), minimumVersion, "v0.14.1-preview"))
owned := map[string]string{}
for _, name := range []string{"internal/svc/serviceContext.go", "internal/config/config.go", "etc/config.yaml"} {
path := filepath.Join(dir, name)
value := readFile(t, path)
if strings.HasSuffix(name, ".go") {
value += "\n// project extension kept\n"
} else {
value += "\n# project configuration kept\n"
}
writeFile(t, path, value)
owned[path] = value
}
plan, err := PlanUpgrade(dir)
if err != nil || len(plan.Changes) != 1 || plan.Changes[0].Path != "go.mod" {
t.Fatal(plan, err)
}
if _, err := ApplyUpgrade(dir); err != nil {
t.Fatal(err)
}
for path, want := range owned {
if readFile(t, path) != want {
t.Fatal("developer file modified", path)
}
}
if _, err := Generate(Options{Dir: dir, API: filepath.Join(dir, "api/service.api"), Check: true}); err != nil {
t.Fatal(err)
}
}
func TestSafeInfrastructureUpgrade(t *testing.T) {
dir := oldInfrastructureProject(t)
before := snapshot(t, dir)
if _, err := Generate(Options{Dir: dir, API: filepath.Join(dir, "api/service.api")}); err == nil {
t.Fatal("legacy constructor accepted")
}
if !sameFiles(before, snapshot(t, dir)) {
t.Fatal("failed generate wrote files")
}
plan, err := PlanUpgrade(dir)
if err != nil || len(plan.Changes) == 0 {
t.Fatal(plan, err)
}
for _, c := range plan.Changes {
if c.Manual {
t.Fatal(c.Path)
}
}
preview := filepath.Join(t.TempDir(), "preview")
if _, err = PreviewUpgrade(dir, preview); err != nil {
t.Fatal(err)
}
if !sameFiles(before, snapshot(t, dir)) {
t.Fatal("preview changed project")
}
logic := readFile(t, filepath.Join(dir, "internal/logic/greet/greet.go"))
if _, err = ApplyUpgrade(dir); err != nil {
t.Fatal(err)
}
if _, err = os.Stat(filepath.Join(dir, "internal/svc/close.go")); !os.IsNotExist(err) {
t.Fatal("old lifecycle remains")
}
if readFile(t, filepath.Join(dir, "internal/logic/greet/greet.go")) != logic {
t.Fatal("business changed")
}
if _, err = Generate(Options{Dir: dir, API: filepath.Join(dir, "api/service.api"), Check: true}); err != nil {
t.Fatal(err)
}
plan, err = PlanUpgrade(dir)
if err != nil || len(plan.Changes) != 0 {
t.Fatal("upgrade not idempotent", plan, err)
}
}
func TestUpgradePreservesCustomFilesAndRollsBack(t *testing.T) {
for _, custom := range []bool{true, false} {
dir := oldInfrastructureProject(t)
if custom {
path := filepath.Join(dir, "internal/svc/serviceContext.go")
writeFile(t, path, readFile(t, path)+"\n// custom dependency\n")
} else {
path := filepath.Join(dir, "internal/logic/greet/greet.go")
writeFile(t, path, "package greet;func(s *Logic)Greet(){}")
}
before := snapshot(t, dir)
if _, err := ApplyUpgrade(dir); err == nil {
t.Fatal("unsafe upgrade accepted")
}
if !sameFiles(before, snapshot(t, dir)) {
t.Fatal("failed upgrade changed project")
}
}
}