-
Notifications
You must be signed in to change notification settings - Fork 340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add post-{commit,merge} #857
Changes from 4 commits
1963648
4538ae7
67aa5a2
1d173cb
646e9e0
5000139
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,7 @@ import ( | |
|
||
"github.com/davecgh/go-spew/spew" | ||
|
||
"github.com/treeverse/lakefs/db" | ||
"github.com/treeverse/lakefs/testutil" | ||
) | ||
|
||
|
@@ -283,8 +284,61 @@ func TestCataloger_CommitTombstoneShouldNotChangeHistory(t *testing.T) { | |
ent, err := c.GetEntry(ctx, repository, branchCommit.Reference, "file42", GetEntryParams{}) | ||
testutil.MustDo(t, "get entry from create branch commit - branch1", err) | ||
|
||
checksumFile42 := testCreateEntryCalcChecksum("file42", "") | ||
checksumFile42 := testCreateEntryCalcChecksum("file42", t.Name(), "") | ||
if ent.Checksum != checksumFile42 { | ||
t.Fatalf("get entry from branch commit checksum=%s, expected, %s", ent.Checksum, checksumFile42) | ||
} | ||
} | ||
|
||
func TestCataloger_CommitHooks(t *testing.T) { | ||
ctx := context.Background() | ||
c := testCataloger(t) | ||
|
||
t.Run("commit hooks run and see commit", func(t *testing.T) { | ||
repository := testCatalogerRepo(t, ctx, c, "repository", "master") | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can take out of the repo creation out of both tests There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Every other test does that too. We can refactor in a separate PR. |
||
checksum := testCatalogerCreateEntry(t, ctx, c, repository, DefaultBranchName, "/file1", nil, "") | ||
var logs [2][]*CommitLog | ||
for i := 0; i < 2; i++ { | ||
j := i | ||
c.Hooks().AddPostCommit(func(_ context.Context, _ db.Tx, l *CommitLog) error { | ||
logs[j] = append(logs[j], l) | ||
return nil | ||
}) | ||
} | ||
|
||
commitLog, err := c.Commit(ctx, repository, "master", "commit "+t.Name(), "tester", Metadata{"foo": "bar"}) | ||
if err != nil { | ||
t.Fatalf("commit entry: %s", err) | ||
} | ||
|
||
for i, log := range logs { | ||
if len(log) != 1 || log[0] != commitLog { | ||
t.Errorf("hook %d: expected one commit %+v but got %+v", i, commitLog, log) | ||
} | ||
} | ||
|
||
entry, err := c.GetEntry(ctx, repository, "master:HEAD", "/file1", GetEntryParams{}) | ||
if err != nil || entry.Path != "/file1" || entry.Checksum != checksum { | ||
t.Errorf("expected /file1 committed, got %+v, %s", entry, err) | ||
} | ||
}) | ||
|
||
t.Run("commit hooks can block commit", func(t *testing.T) { | ||
repository := testCatalogerRepo(t, ctx, c, "repository", "master") | ||
testCatalogerCreateEntry(t, ctx, c, repository, "master", "/file1", nil, "") | ||
testingErr := fmt.Errorf("you know, for testing!") | ||
c.Hooks().AddPostCommit(func(_ context.Context, _ db.Tx, _ *CommitLog) error { | ||
return testingErr | ||
}) | ||
|
||
commitLog, err := c.Commit(ctx, repository, "master", "commit "+t.Name(), "tester", Metadata{"foo": "bar"}) | ||
if !errors.Is(err, testingErr) { | ||
t.Errorf("expected commit to fail with %s but got %v, %s", testingErr, commitLog, err) | ||
} | ||
|
||
entry, err := c.GetEntry(ctx, repository, "master:HEAD", "/file1", GetEntryParams{}) | ||
if !errors.Is(err, db.ErrNotFound) { | ||
t.Errorf("expected not to find /file1 because its commit rolled back, got %+v, %s", entry, err) | ||
} | ||
}) | ||
} | ||
arielshaqed marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,12 +3,14 @@ package catalog | |
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
"strconv" | ||
"testing" | ||
|
||
"github.com/go-test/deep" | ||
|
||
"github.com/davecgh/go-spew/spew" | ||
"github.com/treeverse/lakefs/db" | ||
"github.com/treeverse/lakefs/testutil" | ||
) | ||
|
||
|
@@ -86,8 +88,7 @@ func TestCataloger_Merge_FromParentNoChangesInChild(t *testing.T) { | |
// Difference{Type: DifferenceTypeRemoved, Path: "/file1"}, | ||
//} | ||
//if !differences.Equal(expectedDifferences) { | ||
// t.Fatalf("Merge differences = %s, expected %s", spew.Sdump(differences), spew.Sdump(expectedDifferences)) | ||
//} | ||
// t.Fatalf("Merge differences = %s, expected %s", spew.Sdump(differences), spew.Sdump(expectedDifferences))} | ||
} | ||
|
||
func TestCataloger_Merge_FromParentConflicts(t *testing.T) { | ||
|
@@ -1106,7 +1107,7 @@ func TestCataloger_MergeOverDeletedEntries(t *testing.T) { | |
testutil.MustDo(t, "merge master to b1", err) | ||
ent, err := c.GetEntry(ctx, repository, "b1", "fileX", GetEntryParams{}) | ||
testutil.MustDo(t, "get entry again from b1", err) | ||
expectedChecksum := testCreateEntryCalcChecksum("fileX", "master2") | ||
expectedChecksum := testCreateEntryCalcChecksum("fileX", t.Name(), "master2") | ||
if ent.Checksum != expectedChecksum { | ||
t.Fatalf("Get file checksum after merge=%s, expected %s", ent.Checksum, expectedChecksum) | ||
} | ||
|
@@ -1200,3 +1201,60 @@ func TestCataloger_MergeFromChildAfterMergeFromParent(t *testing.T) { | |
t.Fatalf("Merge err=%s, expected none", err) | ||
} | ||
} | ||
|
||
func TestCataloger_Merge_Hooks(t *testing.T) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. let me know what you think about the diff test code - if you think it is easier to read, update this one - max I can live with both cases or give you the code for this one. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Will copy that code over here, you're correct that it's a bit nicer. |
||
for _, success := range []bool{true, false} { | ||
test := "pass" | ||
if !success { | ||
test = "fail" | ||
} | ||
testingErr := fmt.Errorf("you know, for testing!") | ||
t.Run(test, func(t *testing.T) { | ||
ctx := context.Background() | ||
c := testCataloger(t) | ||
var gotMergeResult *MergeResult | ||
if success { | ||
c.Hooks().AddPostMerge( | ||
func(_ context.Context, _ db.Tx, mergeResult *MergeResult) error { | ||
if gotMergeResult != nil { | ||
return fmt.Errorf("success merge hook called twice, %+v then %+v", gotMergeResult, mergeResult) | ||
} | ||
gotMergeResult = mergeResult | ||
return nil | ||
}) | ||
} else { | ||
c.Hooks().AddPostMerge( | ||
func(_ context.Context, _ db.Tx, _ *MergeResult) error { | ||
return testingErr | ||
}) | ||
} | ||
|
||
repository := testCatalogerRepo(t, ctx, c, "repo", "master") | ||
|
||
// create branch based on master | ||
testCatalogerBranch(t, ctx, c, repository, "branch1", "master") | ||
|
||
// create file to merge | ||
testCatalogerCreateEntry(t, ctx, c, repository, "branch1", "/file1", nil, "") | ||
_, err := c.Commit(ctx, repository, "branch1", "commit to master", "tester", nil) | ||
testutil.MustDo(t, "commit to branch1", err) | ||
|
||
res, err := c.Merge(ctx, repository, "master", "branch1", "tester", "", nil) | ||
if success { | ||
if err != nil { | ||
t.Error("Merge from master to branch1 failed:", err) | ||
} | ||
testVerifyEntries(t, ctx, c, repository, "branch1", []testEntryInfo{ | ||
{Path: "/file1"}, | ||
}) | ||
if diffs := deep.Equal(res, gotMergeResult); diffs != nil { | ||
t.Error("hook received unexpected merge result: ", diffs) | ||
} | ||
} else { | ||
if !errors.Is(err, testingErr) { | ||
t.Error("hook did not fail merge: ", err) | ||
} | ||
} | ||
}) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,9 +53,10 @@ func testCatalogerBranch(t testing.TB, ctx context.Context, c Cataloger, reposit | |
} | ||
} | ||
|
||
func testCatalogerCreateEntry(t testing.TB, ctx context.Context, c Cataloger, repository, branch, path string, metadata Metadata, seed string) { | ||
// testCatalogerCreateEntry creates a test entry on cataloger, returning a (fake) checksum based on the path, the test name, and a seed. | ||
func testCatalogerCreateEntry(t testing.TB, ctx context.Context, c Cataloger, repository, branch, path string, metadata Metadata, seed string) string { | ||
t.Helper() | ||
checksum := testCreateEntryCalcChecksum(path, seed) | ||
checksum := testCreateEntryCalcChecksum(path, t.Name(), seed) | ||
var size int64 | ||
for i := range checksum { | ||
size += int64(checksum[i]) | ||
|
@@ -70,6 +71,7 @@ func testCatalogerCreateEntry(t testing.TB, ctx context.Context, c Cataloger, re | |
if err != nil { | ||
t.Fatalf("Failed to create entry %s on branch %s, repository %s: %s", path, branch, repository, err) | ||
} | ||
return checksum | ||
} | ||
|
||
func testCatalogerGetEntry(t testing.TB, ctx context.Context, c Cataloger, repository, reference, path string, expect bool) { | ||
|
@@ -83,9 +85,9 @@ func testCatalogerGetEntry(t testing.TB, ctx context.Context, c Cataloger, repos | |
} | ||
} | ||
|
||
func testCreateEntryCalcChecksum(key string, seed string) string { | ||
func testCreateEntryCalcChecksum(key string, testName string, seed string) string { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the plan was to pass the test name as seed if needed and call this function. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The problem is that if any 2 tests use the same key and seed then they clash. It caused an actual problem when I copied calls around. |
||
h := sha256.New() | ||
_, _ = h.Write([]byte(seed)) | ||
_, _ = h.Write([]byte(testName + seed)) | ||
_, _ = h.Write([]byte(key)) | ||
checksum := hex.EncodeToString(h.Sum(nil)) | ||
return checksum | ||
|
@@ -101,7 +103,7 @@ func testVerifyEntries(t testing.TB, ctx context.Context, c Cataloger, repositor | |
} | ||
} else { | ||
testutil.MustDo(t, fmt.Sprintf("Get entry=%s, repository=%s, reference=%s", entry.Path, repository, reference), err) | ||
expectedAddr := testCreateEntryCalcChecksum(entry.Path, entry.Seed) | ||
expectedAddr := testCreateEntryCalcChecksum(entry.Path, t.Name(), entry.Seed) | ||
if ent.PhysicalAddress != expectedAddr { | ||
t.Fatalf("Get entry %s, addr = %s, expected %s", entry.Path, ent.PhysicalAddress, expectedAddr) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe add a branch filter by name/regex?
o.w. you're relying on the hook itself to filter by it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shall not do this. If needed in >1 hooks, we could add a wrapper ("decorator") function that filters a hook implementation for regexp. The added complexity of doing it here would include special semantics for merges -- there are two branches here.
Finally, I'm not sure it will be useful. For exports it's not, because it is hard to precompute the regexp (changes transactionally with the DB) and easy to check directly on the DB.