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  }