Still frustratingly incomplete, as we're not actually testing the
rollback cases which the transaction writer is really supposed to
facilitate.
This commit is contained in:
sam boyer 2016-12-30 00:39:08 -05:00 коммит произвёл Jess Frazelle
Родитель 31e7a7599f
Коммит ea0f0f03d7
2 изменённых файлов: 215 добавлений и 5 удалений

Просмотреть файл

@ -89,14 +89,14 @@ func (sw safeWriter) writeAllSafe(forceVendor bool) error {
return nil
}
if writeV && sw.l == nil && sw.nl == nil {
return errors.New("must provide a lock in order to write out vendor")
}
if writeV && sw.sm == nil {
return errors.New("must provide a SourceManager if writing out a vendor dir.")
}
if writeV && sw.l == nil && sw.nl == nil {
return errors.New("must provide a lock in order to write out vendor")
}
mpath := filepath.Join(sw.root, manifestName)
lpath := filepath.Join(sw.root, lockName)
vpath := filepath.Join(sw.root, "vendor")
@ -129,7 +129,13 @@ func (sw safeWriter) writeAllSafe(forceVendor bool) error {
}
if writeV {
err = gps.WriteDepTree(filepath.Join(td, "vendor"), sw.nl, sw.sm, true)
// prefer the nl, but take the l if only that's available, as could be the
// case if true was passed for forceVendor
l := sw.nl
if l == nil {
l = sw.l
}
err = gps.WriteDepTree(filepath.Join(td, "vendor"), l, sw.sm, true)
if err != nil {
return errors.Wrap(err, "error while writing out vendor tree")
}

204
txn_writer_test.go Normal file
Просмотреть файл

@ -0,0 +1,204 @@
package main
import (
"os"
"path/filepath"
"strconv"
"strings"
"testing"
)
func TestTxnWriterBadInputs(t *testing.T) {
tg := testgo(t)
defer tg.cleanup()
tg.tempDir("txnwriter")
td := tg.path(".")
sw := safeWriter{}
// no root
if err := sw.writeAllSafe(false); err == nil {
t.Errorf("should have errored without a root path, but did not")
}
sw.root = td
if err := sw.writeAllSafe(false); err != nil {
t.Errorf("write with only root should be fine, just a no-op, but got err %q", err)
}
if err := sw.writeAllSafe(true); err == nil {
t.Errorf("should fail because no source manager was provided for writing vendor")
}
if err := sw.writeAllSafe(true); err == nil {
t.Errorf("should fail because no lock was provided from which to write vendor")
}
// now check dir validation
sw.root = filepath.Join(td, "nonexistent")
if err := sw.writeAllSafe(false); err == nil {
t.Errorf("should have errored with nonexistent dir for root path, but did not")
}
sw.root = filepath.Join(td, "myfile")
srcf, err := os.Create(sw.root)
if err != nil {
t.Fatal(err)
}
srcf.Close()
if err := sw.writeAllSafe(false); err == nil {
t.Errorf("should have errored when root path is a file, but did not")
}
}
func TestTxnWriter(t *testing.T) {
needsExternalNetwork(t)
needsGit(t)
tg := testgo(t)
tg.tempDir("")
defer tg.cleanup()
var c *ctx
c = &ctx{
GOPATH: tg.path("."),
}
sm, err := c.sourceManager()
tg.must(err)
var sw safeWriter
var mpath, lpath, vpath string
var count int
reset := func() {
pr := filepath.Join("src", "txnwriter"+strconv.Itoa(count))
tg.tempDir(pr)
sw = safeWriter{
root: tg.path(pr),
sm: sm,
}
tg.cd(sw.root)
mpath = filepath.Join(sw.root, manifestName)
lpath = filepath.Join(sw.root, lockName)
vpath = filepath.Join(sw.root, "vendor")
count++
}
reset()
// super basic manifest and lock
expectedManifest := `{
"dependencies": {
"github.com/sdboyer/dep-test": {
"version": "1.0.0"
}
}
}
`
expectedLock := `{
"memo": "595716d270828e763c811ef79c9c41f85b1d1bfbdfe85280036405c03772206c",
"projects": [
{
"name": "github.com/sdboyer/dep-test",
"version": "1.0.0",
"revision": "2a3a211e171803acb82d1d5d42ceb53228f51751",
"packages": [
"."
]
}
]
}
`
m, err := readManifest(strings.NewReader(expectedManifest))
tg.must(err)
l, err := readLock(strings.NewReader(expectedLock))
tg.must(err)
// Just write manifest
sw.m = m
tg.must(sw.writeAllSafe(false))
tg.mustExist(mpath)
tg.mustNotExist(lpath)
tg.mustNotExist(vpath)
diskm := tg.readManifest()
if diskm != expectedManifest {
t.Fatalf("expected %s, got %s", expectedManifest, diskm)
}
// Manifest and lock, but no vendor
sw.l = l
tg.must(sw.writeAllSafe(false))
tg.mustExist(mpath)
tg.mustExist(lpath)
tg.mustNotExist(vpath)
diskm = tg.readManifest()
if diskm != expectedManifest {
t.Fatalf("expected %s, got %s", expectedManifest, diskm)
}
diskl := tg.readLock()
if diskl != expectedLock {
t.Fatalf("expected %s, got %s", expectedLock, diskl)
}
tg.must(sw.writeAllSafe(true))
tg.mustExist(mpath)
tg.mustExist(lpath)
tg.mustExist(vpath)
tg.mustExist(filepath.Join(vpath, "github.com", "sdboyer", "dep-test"))
diskm = tg.readManifest()
if diskm != expectedManifest {
t.Fatalf("expected %s, got %s", expectedManifest, diskm)
}
diskl = tg.readLock()
if diskl != expectedLock {
t.Fatalf("expected %s, got %s", expectedLock, diskl)
}
// start fresh, ignoring the manifest now
reset()
sw.l = l
sw.nl = l
tg.must(sw.writeAllSafe(false))
// locks are equivalent, so nothing gets written
tg.mustNotExist(mpath)
tg.mustNotExist(lpath)
tg.mustNotExist(vpath)
l2 := &lock{}
*l2 = *l
// zero out the input hash to ensure non-equivalency
l2.Memo = []byte{}
sw.l = l2
tg.must(sw.writeAllSafe(true))
tg.mustNotExist(mpath)
tg.mustExist(lpath)
tg.mustExist(vpath)
tg.mustExist(filepath.Join(vpath, "github.com", "sdboyer", "dep-test"))
diskl = tg.readLock()
if diskl != expectedLock {
t.Fatalf("expected %s, got %s", expectedLock, diskl)
}
// repeat op to ensure good behavior when vendor dir already exists
sw.l = nil
tg.must(sw.writeAllSafe(true))
tg.mustNotExist(mpath)
tg.mustExist(lpath)
tg.mustExist(vpath)
tg.mustExist(filepath.Join(vpath, "github.com", "sdboyer", "dep-test"))
diskl = tg.readLock()
if diskl != expectedLock {
t.Fatalf("expected %s, got %s", expectedLock, diskl)
}
// TODO test txn rollback cases. maybe we can force errors with chmodding?
}