Skip to content

Commit

Permalink
Migrate tests to new transaction API
Browse files Browse the repository at this point in the history
Requires repository, base branch everywhere.

Right now, we solve all file puts by interpolating the string in-place
with `tx.branch` instead of `temp_branch`. This is relatively ugly, and
could be better with transaction APIs that change state on the branch
(puts, rms).
However, those need a check that the input path can be
relative, since we just by default assume the user wants to put on the
ephemeral branch.
  • Loading branch information
nicholasjng committed Jan 25, 2024
1 parent 3d920bf commit 96f162a
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 112 deletions.
24 changes: 12 additions & 12 deletions tests/test_put_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,24 @@ def test_no_change_postcommit(
random_file = random_file_factory.make()

lpath = str(random_file)
rpath = f"{repository.id}/{temp_branch.id}/{random_file.name}"
message = f"Add file {random_file.name}"

with fs.transaction as tx:
fs.put(lpath, rpath, precheck=False, autocommit=False)
tx.commit(repository, temp_branch, message=f"Add file {random_file.name}")
with fs.transaction(repository, temp_branch) as tx:
fs.put(lpath, f"{repository.id}/{tx.branch.id}/{random_file.name}")
tx.commit(message=message)

commits = list(temp_branch.log())
latest_commit = commits[0] # commit log is ordered branch-tip-first
assert latest_commit.message == f"Add file {random_file.name}"
commits = list(temp_branch.log(max_amount=2))
current_head = temp_branch.head.get_commit()
assert commits[0].message.startswith("Merge")
assert commits[1].message == message

# put the same file again, this time the diff is empty
with fs.transaction as tx:
fs.put(lpath, rpath, precheck=False, autocommit=False)
tx.commit(repository, temp_branch, message=f"Add file {random_file.name}")
with fs.transaction(repository, temp_branch) as tx:
fs.put(lpath, f"{repository.id}/{tx.branch.id}/{random_file.name}", precheck=False)
tx.commit(message=f"Add file {random_file.name}")

# check that no other commit has happened.
commits = list(temp_branch.log())
assert commits[0] == latest_commit
assert temp_branch.head.get_commit() == current_head


def test_implicit_branch_creation(
Expand Down
18 changes: 9 additions & 9 deletions tests/test_rm.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,22 @@ def test_rm(
assert not fs.exists(path)


def test_rm_with_postcommit(
def test_rm_with_transaction(
fs: LakeFSFileSystem,
repository: Repository,
temp_branch: Branch,
) -> None:
path = f"{repository.id}/{temp_branch.id}/README.md"
msg = "Remove file README.md"
message = "Remove file README.md"

with fs.transaction as tx:
fs.rm(path)
tx.commit(repository, temp_branch, message=msg)
assert not fs.exists(path)
with fs.transaction(repository, temp_branch, automerge=True) as tx:
fs.rm(f"{repository.id}/{tx.branch.id}/README.md")
tx.commit(message=message)

commits = list(temp_branch.log())
latest_commit = commits[0]
assert latest_commit.message == msg
commits = list(temp_branch.log(max_amount=2))
assert not fs.exists(path)
assert commits[-1].message == message
assert commits[0].message.startswith("Merge")


def test_rm_recursive(
Expand Down
126 changes: 35 additions & 91 deletions tests/test_transactions.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
from pathlib import Path
from typing import Any

import pytest
from lakefs.branch import Branch
from lakefs.reference import Commit, Reference
from lakefs.repository import Repository

from lakefs_spec import LakeFSFileSystem
from lakefs_spec.transaction import Placeholder
from tests.util import RandomFileFactory, put_random_file_on_branch, with_counter
from tests.util import RandomFileFactory


def test_transaction_commit(
Expand All @@ -24,38 +20,31 @@ def test_transaction_commit(

message = f"Add file {random_file.name}"

with fs.transaction as tx:
fs.put_file(lpath, rpath)
with fs.transaction(repository, temp_branch) as tx:
fs.put_file(lpath, f"{repository.id}/{tx.branch.id}/{random_file.name}")
assert len(tx.files) == 1
# sha is a placeholder for the actual SHA created on transaction completion.
sha = tx.commit(repository, temp_branch, message=message)
# stack contains the file to upload, and the commit op.
assert len(tx.files) == 2
assert not sha.available
sha = tx.commit(message=message)

assert sha.available

commits = list(temp_branch.log())
latest_commit = commits[0]
assert latest_commit.message == message
assert latest_commit.id == sha.id
# HEAD should be the merge commit.
head_tilde = list(temp_branch.log(max_amount=2))[-1]
assert head_tilde.message == message
assert head_tilde.id == sha.id


def test_transaction_tag(fs: LakeFSFileSystem, repository: Repository) -> None:
try:
# tag gets created on exit of the context.
with fs.transaction as tx:
sha = tx.rev_parse(repository, "main")
tag = tx.tag(repository, ref=sha, tag="v2")

assert sha.available
with fs.transaction(repository) as tx:
sha = tx.rev_parse("main")
tag = tx.tag(sha, tag="v2")

tags = list(repository.tags())
assert len(tags) > 0
assert tags[0].id == tag
assert tags[0].id == tag.id
assert tags[0].get_commit().id == sha.id
finally:
repository.tag(tag).delete()
tag.delete()


def test_transaction_merge(
Expand All @@ -71,20 +60,20 @@ def test_transaction_merge(
resource = f"{repository.id}/{new_branch.id}/{random_file.name}"
message = "Commit new file"

with fs.transaction as tx:
with fs.transaction(repository, new_branch) as tx:
lpath = str(random_file)
# stage a file on new_branch...
fs.put_file(str(random_file), resource)
fs.put_file(lpath, f"{repository.id}/{tx.branch.id}/{random_file.name}")
# ... commit it with the above message
tx.commit(repository, new_branch, message)
tx.commit(message=message)
# ... and merge it into temp_branch.
tx.merge(repository, new_branch, into=temp_branch)

# at last, verify temp_branch@HEAD is the merge commit.
commits = list(temp_branch.log())
assert len(commits) > 2
latest_commit = commits[0]
assert latest_commit.message == f"Merge {new_branch.id!r} into {temp_branch.id!r}"
second_latest_commit = commits[1]
tx.merge(new_branch, into=temp_branch)

# at last, verify temp_branch~ is the merge commit.
commits = list(temp_branch.log(max_amount=3))
head_tilde = commits[1]
assert head_tilde.message == f"Merge {new_branch.id!r} into {temp_branch.id!r}"
second_latest_commit = commits[2]
assert second_latest_commit.message == message


Expand All @@ -101,33 +90,14 @@ def test_transaction_revert(

message = f"Add file {random_file.name}"

with fs.transaction as tx:
fs.put_file(lpath, rpath, autocommit=False)
tx.commit(repository, temp_branch, message=message)
tx.revert(repository, temp_branch)

commits = list(temp_branch.log())
assert len(commits) > 1
latest_commit = commits[0]
assert latest_commit.message == f"Revert {temp_branch.id}"


def test_transaction_branch(fs: LakeFSFileSystem, repository: Repository) -> None:
branch = "new-hello"

try:
with fs.transaction as tx:
tx.create_branch(repository, branch, source="main")

assert branch in [b.id for b in list(repository.branches())]
finally:
repository.branch(branch).delete()

with fs.transaction(repository, temp_branch) as tx:
fs.put_file(lpath, f"{repository.id}/{tx.branch.id}/{random_file.name}")
tx.commit(message=message)
tx.revert(temp_branch, temp_branch.head)

def test_transaction_entry(fs: LakeFSFileSystem) -> None:
fs.start_transaction()
assert fs._intrans
assert fs._transaction is not None
head, head_tilde = list(temp_branch.log(max_amount=2))
assert head.message.startswith("Merge")
assert head_tilde.message.startswith("Revert")


def test_transaction_failure(
Expand All @@ -143,39 +113,13 @@ def test_transaction_failure(

message = f"Add file {random_file.name}"

fs.client, counter = with_counter(fs.client)
try:
with fs.transaction as tx:
fs.put_file(lpath, rpath)
tx.commit(repository, temp_branch, message=message)
with fs.transaction(repository, temp_branch) as tx:
fs.put_file(lpath, f"{repository.id}/{tx.branch.id}/{random_file.name}")
tx.commit(message=message)
raise RuntimeError("something went wrong")
except RuntimeError:
pass

# assert that no commit happens because of the exception.
assert counter.count("commits_api.commit") == 0


def test_placeholder_representations(
random_file_factory: RandomFileFactory,
fs: LakeFSFileSystem,
repository: Repository,
temp_branch: Branch,
) -> None:
with fs.transaction as tx:
rpath = put_random_file_on_branch(random_file_factory, fs, repository, temp_branch)
message = f"Add file {Path(rpath).name}"
sha = tx.commit(repository, temp_branch, message=message)

assert isinstance(sha, Reference)
commits = list(temp_branch.log())
latest_commit = commits[0]
assert sha.id == latest_commit.id
assert repr(sha.id) == repr(latest_commit.id)


def test_unfilled_placeholder_error() -> None:
p: Placeholder[Commit] = Placeholder()

with pytest.raises(RuntimeError):
_ = p.value
assert not fs.exists(rpath)

0 comments on commit 96f162a

Please sign in to comment.