github.com/qri-io/qri@v0.10.1-0.20220104210721-c771715036cb/lib/test_runner_test.go (about) 1 package lib 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 "strings" 11 "testing" 12 "time" 13 14 "github.com/qri-io/dataset" 15 "github.com/qri-io/qri/base" 16 "github.com/qri-io/qri/base/dsfs" 17 testcfg "github.com/qri-io/qri/config/test" 18 "github.com/qri-io/qri/dsref" 19 "github.com/qri-io/qri/logbook" 20 "github.com/qri-io/qri/profile" 21 remotemock "github.com/qri-io/qri/remote/mock" 22 ) 23 24 type testRunner struct { 25 Ctx context.Context 26 Instance *Instance 27 Pwd string 28 TmpDir string 29 WorkDir string 30 dsfsTs func() time.Time 31 bookTs func() int64 32 } 33 34 func newTestRunner(t *testing.T) *testRunner { 35 ctx := context.Background() 36 dsfsCounter := 0 37 dsfsTsFunc := dsfs.Timestamp 38 dsfs.Timestamp = func() time.Time { 39 dsfsCounter++ 40 return time.Date(2001, 01, 01, 01, dsfsCounter, 01, 01, time.UTC) 41 } 42 43 bookCounter := 0 44 bookTsFunc := logbook.NewTimestamp 45 logbook.NewTimestamp = func() int64 { 46 bookCounter++ 47 return time.Date(2001, 01, 01, 01, bookCounter, 01, 01, time.UTC).Unix() 48 } 49 50 pwd, err := os.Getwd() 51 if err != nil { 52 t.Fatal(err) 53 } 54 55 // A temporary directory for doing filesystem work. 56 tmpDir, err := ioutil.TempDir("", "lib_test_runner") 57 if err != nil { 58 t.Fatal(err) 59 } 60 61 qriPath := filepath.Join(tmpDir, "qri") 62 if err := os.Mkdir(qriPath, os.ModePerm); err != nil { 63 t.Fatal(err) 64 } 65 cfg := testcfg.DefaultMemConfigForTesting() 66 67 // create new instance! 68 inst, err := NewInstance( 69 ctx, 70 // NewInstance requires a qriPath, even if the repo & all stores are in mem 71 qriPath, 72 OptConfig(cfg), 73 // ensure we create a mock registry client for testing 74 OptRemoteClientConstructor(remotemock.NewClient), 75 ) 76 if err != nil { 77 t.Fatal(err) 78 } 79 return &testRunner{ 80 Ctx: ctx, 81 // TODO (b5) - move test profile creation into testRunner constructor 82 Instance: inst, 83 TmpDir: tmpDir, 84 Pwd: pwd, 85 dsfsTs: dsfsTsFunc, 86 bookTs: bookTsFunc, 87 } 88 } 89 90 func (tr *testRunner) Delete() { 91 dsfs.Timestamp = tr.dsfsTs 92 logbook.NewTimestamp = tr.bookTs 93 os.Chdir(tr.Pwd) 94 os.RemoveAll(tr.TmpDir) 95 } 96 97 func (tr *testRunner) MustOwner(t *testing.T) *profile.Profile { 98 owner, err := tr.Instance.activeProfile(tr.Ctx) 99 if err != nil { 100 t.Fatal(err) 101 } 102 return owner 103 } 104 105 func (tr *testRunner) MustReadFile(t *testing.T, filename string) string { 106 data, err := ioutil.ReadFile(filename) 107 if err != nil { 108 t.Fatal(err) 109 } 110 return string(data) 111 } 112 113 func (tr *testRunner) MustWriteTmpFile(t *testing.T, filename, data string) string { 114 path := filepath.Join(tr.TmpDir, filename) 115 tr.MustWriteFile(t, path, data) 116 return path 117 } 118 119 func (tr *testRunner) MustWriteFile(t *testing.T, filename, data string) { 120 if err := ioutil.WriteFile(filename, []byte(data), 0644); err != nil { 121 t.Fatal(err) 122 } 123 } 124 125 func (tr *testRunner) MakeTmpFilename(filename string) (path string) { 126 return filepath.Join(tr.TmpDir, filename) 127 } 128 129 func (tr *testRunner) NiceifyTempDirs(text string) string { 130 // Replace the temporary directory 131 text = strings.Replace(text, tr.TmpDir, "/tmp", -1) 132 // Replace that same directory with symlinks resolved 133 realTmp, err := filepath.EvalSymlinks(tr.TmpDir) 134 if err == nil { 135 text = strings.Replace(text, realTmp, "/tmp", -1) 136 } 137 return text 138 } 139 140 func (tr *testRunner) ChdirToRoot() { 141 os.Chdir(tr.TmpDir) 142 } 143 144 func (tr *testRunner) CreateAndChdirToWorkDir(subdir string) string { 145 tr.WorkDir = PathJoinPosix(tr.TmpDir, subdir) 146 err := os.Mkdir(tr.WorkDir, 0755) 147 if err != nil { 148 panic(err) 149 } 150 err = os.Chdir(tr.WorkDir) 151 if err != nil { 152 panic(err) 153 } 154 return tr.WorkDir 155 } 156 157 func (tr *testRunner) MustSaveFromBody(t *testing.T, dsName, bodyFilename string) *dataset.Dataset { 158 if !dsref.IsValidName(dsName) { 159 t.Fatalf("invalid dataset name: %q", dsName) 160 } 161 pro, err := tr.Instance.activeProfile(tr.Ctx) 162 if err != nil { 163 t.Fatalf("error getting active profile: %s", err) 164 } 165 p := SaveParams{ 166 Ref: fmt.Sprintf("%s/%s", pro.Peername, dsName), 167 BodyPath: bodyFilename, 168 } 169 res, err := tr.Instance.Dataset().Save(tr.Ctx, &p) 170 if err != nil { 171 t.Fatal(err) 172 } 173 return res 174 } 175 176 func (tr *testRunner) SaveWithParams(p *SaveParams) (dsref.Ref, error) { 177 res, err := tr.Instance.Dataset().Save(tr.Ctx, p) 178 if err != nil { 179 return dsref.Ref{}, err 180 } 181 return dsref.ConvertDatasetToVersionInfo(res).SimpleRef(), nil 182 } 183 184 func (tr *testRunner) MustGet(t *testing.T, ref string) *dataset.Dataset { 185 p := GetParams{Ref: ref} 186 res, err := tr.Instance.Dataset().Get(tr.Ctx, &p) 187 if err != nil { 188 t.Fatal(err) 189 } 190 return res.Value.(*dataset.Dataset) 191 } 192 193 func (tr *testRunner) ApplyWithParams(ctx context.Context, p *ApplyParams) (*dataset.Dataset, error) { 194 res, err := tr.Instance.Automation().Apply(ctx, p) 195 if err != nil { 196 return nil, err 197 } 198 return res.Data, nil 199 } 200 201 func (tr *testRunner) Diff(left, right, selector string) (string, error) { 202 p := DiffParams{ 203 LeftSide: left, 204 RightSide: right, 205 UseLeftPrevVersion: right == "", 206 Selector: selector, 207 } 208 r, err := tr.Instance.Diff().Diff(tr.Ctx, &p) 209 if err != nil { 210 return "", err 211 } 212 data, err := json.Marshal(*r) 213 if err != nil { 214 return "", err 215 } 216 return string(data), nil 217 } 218 219 func (tr *testRunner) DiffWithParams(p *DiffParams) (string, error) { 220 r, err := tr.Instance.Diff().Diff(tr.Ctx, p) 221 if err != nil { 222 return "", err 223 } 224 data, err := json.Marshal(*r) 225 if err != nil { 226 return "", err 227 } 228 return string(data), nil 229 } 230 231 func (tr *testRunner) MustWhatChanged(t *testing.T, ref string) []base.StatusItem { 232 p := WhatChangedParams{Ref: ref} 233 items, err := tr.Instance.Dataset().WhatChanged(tr.Ctx, &p) 234 if err != nil { 235 t.Fatal(err) 236 } 237 return items 238 }