Skip to content

Commit

Permalink
Python integration test for changesSinceV2: File changes
Browse files Browse the repository at this point in the history
Summary:
# Context

We are introducing EdenFS notifications to support scalable and ergonomic file system notifications for EdenFS mounts.

# This Diff

This diff adds a python integration test for changesSinceV2

Windows exceptions will be refactored in the next diff

# Technical Details

This diff is the basis for changesSinceV2's integration test. This test uses the python client for changesSinceV2.

This diff:
File changes - Added/Modified/Removed/Replaced/Renamed

Expected cases:
Directory changes
commit changes
Other large changes

# Discussion Points

Reviewed By: jdelliot

Differential Revision: D66255654

fbshipit-source-id: 12b1bc928285deecdd8c6f51d8f69f898552f2ba
  • Loading branch information
Chris Dinh authored and facebook-github-bot committed Nov 23, 2024
1 parent 9f06877 commit e322f04
Showing 1 changed file with 180 additions and 0 deletions.
180 changes: 180 additions & 0 deletions eden/integration/changes_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,23 @@

# pyre-unsafe

import sys
import time
import unittest
from typing import Optional

from facebook.eden.ttypes import (
Added,
ChangeNotification,
ChangesSinceV2Params,
ChangesSinceV2Result,
Dtype,
LargeChangeNotification,
LostChangesReason,
Modified,
Removed,
Renamed,
Replaced,
SmallChangeNotification,
)

Expand All @@ -36,6 +45,56 @@ def getLargeChangeSafe(
return None


def buildSmallChange(
changeType: SmallChangeNotification,
fileType: Dtype,
path: Optional[bytes] = None,
from_path: Optional[bytes] = None,
to_path: Optional[bytes] = None,
) -> ChangeNotification:
if changeType == SmallChangeNotification.ADDED:
assert path
return ChangeNotification(
SmallChangeNotification(added=Added(fileType=fileType, path=path))
)
elif changeType == SmallChangeNotification.MODIFIED:
assert path
return ChangeNotification(
SmallChangeNotification(modified=Modified(fileType=fileType, path=path))
)
elif changeType == SmallChangeNotification.RENAMED:
assert from_path
assert to_path
return ChangeNotification(
smallChange=SmallChangeNotification(
renamed=Renamed(
fileType=fileType,
from_PY_RESERVED_KEYWORD=from_path,
to=to_path,
)
)
)
elif changeType == SmallChangeNotification.REPLACED:
assert from_path
assert to_path
return ChangeNotification(
smallChange=SmallChangeNotification(
replaced=Replaced(
fileType=Dtype.REGULAR,
from_PY_RESERVED_KEYWORD=from_path,
to=to_path,
)
)
)

elif changeType == SmallChangeNotification.REMOVED:
assert path
return ChangeNotification(
SmallChangeNotification(removed=Removed(fileType=fileType, path=path))
)
return ChangeNotification()


@testcase.eden_repo_test
class ChangesTest(testcase.EdenRepoTest):
def populate_repo(self) -> None:
Expand All @@ -57,6 +116,20 @@ def setUp(self) -> None:

self.position = self.client.getCurrentJournalPosition(self.mount_path_bytes)

def check_changes(self, changes, expected_changes) -> bool:
expected_changes_index = 0
for change in changes:
if change == expected_changes[expected_changes_index]:
expected_changes_index += 1
if expected_changes_index == len(expected_changes):
return True
print("Expected changes not found:")
for i in range(expected_changes_index, len(expected_changes)):
print(expected_changes[i])
print("in:")
print(changes)
return False

def getChangesSinceV2(self, position) -> ChangesSinceV2Result:
return self.client.changesSinceV2(
ChangesSinceV2Params(
Expand All @@ -77,3 +150,110 @@ def test_wrong_mount_generation(self):
largeChange.get_lostChanges().reason,
LostChangesReason.EDENFS_REMOUNTED,
)

def test_add_file(self):
position = self.client.getCurrentJournalPosition(self.mount_path_bytes)
self.eden_repo.write_file("test_file", "", add=False)
if sys.platform == "win32":
# Wait for eden to get the PrjFS notification
time.sleep(1)
changes = self.getChangesSinceV2(position=position)
# When adding a file, it is technically written to so there's an additional modified operation
expected_changes = [
buildSmallChange(
SmallChangeNotification.ADDED, Dtype.REGULAR, path=b"test_file"
),
buildSmallChange(
SmallChangeNotification.MODIFIED, Dtype.REGULAR, path=b"test_file"
),
]
if sys.platform == "win32":
# PrjFS notifications only shows up as added, so remove the modified
expected_changes.pop()
self.assertTrue(self.check_changes(changes.changes, expected_changes))

def test_modify_file(self):
self.eden_repo.write_file("test_file", "", add=False)
if sys.platform == "win32":
# Wait for eden to get the PrjFS notification
time.sleep(1)
position = self.client.getCurrentJournalPosition(self.mount_path_bytes)
self.eden_repo.write_file("test_file", "contents", add=False)
if sys.platform == "win32":
# Wait for eden to get the PrjFS notification
time.sleep(1)
changes = self.getChangesSinceV2(position=position)
expected_changes = [
buildSmallChange(
SmallChangeNotification.MODIFIED, Dtype.REGULAR, path=b"test_file"
),
]
self.assertTrue(self.check_changes(changes.changes, expected_changes))

def test_rename_file(self):
self.eden_repo.write_file("test_file", "", add=False)
if sys.platform == "win32":
# Wait for eden to get the PrjFS notification
time.sleep(1)
position = self.client.getCurrentJournalPosition(self.mount_path_bytes)
self.rename("test_file", "best_file")
if sys.platform == "win32":
# Wait for eden to get the PrjFS notification
time.sleep(1)
changes = self.getChangesSinceV2(position=position)
expected_changes = [
buildSmallChange(
SmallChangeNotification.RENAMED,
Dtype.REGULAR,
from_path=b"test_file",
to_path=b"best_file",
),
]
if sys.platform == "win32":
# No renames on windows, the files are added/removed
expected_changes = [
buildSmallChange(
SmallChangeNotification.REMOVED, Dtype.REGULAR, path=b"test_file"
),
buildSmallChange(
SmallChangeNotification.ADDED, Dtype.REGULAR, path=b"best_file"
),
]
self.assertTrue(self.check_changes(changes.changes, expected_changes))

@unittest.skipIf(sys.platform == "win32", "PrjFS does not support replace")
def test_replace_file(self):
self.eden_repo.write_file("test_file", "test_contents", add=False)
self.eden_repo.write_file("gone_file", "replaced_contents", add=False)
position = self.client.getCurrentJournalPosition(self.mount_path_bytes)
self.rename("test_file", "gone_file")
changes = self.getChangesSinceV2(position=position)
expected_changes = [
buildSmallChange(
SmallChangeNotification.REPLACED,
Dtype.REGULAR,
from_path=b"test_file",
to_path=b"gone_file",
),
]
self.assertTrue(self.check_changes(changes.changes, expected_changes))

def test_remove_file(self):
self.eden_repo.write_file("test_file", "", add=False)
if sys.platform == "win32":
# Wait for eden to get the PrjFS notification
time.sleep(1)
position = self.client.getCurrentJournalPosition(self.mount_path_bytes)
self.rm("test_file")
if sys.platform == "win32":
# Wait for eden to get the PrjFS notification
time.sleep(1)
changes = self.getChangesSinceV2(position=position)
expected_changes = [
buildSmallChange(
SmallChangeNotification.REMOVED,
Dtype.REGULAR,
path=b"test_file",
),
]
self.assertTrue(self.check_changes(changes.changes, expected_changes))

0 comments on commit e322f04

Please sign in to comment.