sapling/eden/integration/casing_test.py
Xavier Deguillard a935fc38b4 inodes: fix casing issue on Windows
Summary:
On Windows, paths are case insensitive (but the filesystem is case preserving),
and thus `open("FILE.TXT")` and `open("file.txt")` refer to the same file. When
that file is not materialized and its parent directory isn't yet enumerated,
PrjFS will call the PRJ_GET_PLACEHOLDER_INFO_CB with the file name passed in to
the `open` call. In this callback, if the passed in name refers to a valid
file, it needs to call PrjWritePlaceholderInfo to populate the directory entry.
Here is what the documentation for that function states:

"For example, if the PRJ_GET_PLACEHOLDER_INFO_CB callback specifies
dir1\dir1\FILE.TXT in callbackData->FilePathName, and the provider's backing
store contains a file called File.txt in the dir1\dir2 directory, and
PrjFileNameCompare returns 0 when comparing the names FILE.TXT and
File.txt, then the provider specifies dir1\dir2\File.txt as the value of
this parameter."

While the documentation doesn't state how that name is used internally, we can
infer (and test) that the returned case will be used as the canonical
representation of that file, ie: the one that a directory listing will see.

Since the PathMap code already does a case insensitive search, we just need to
make sure to use what it returns instead of re-using the name used for the search.

The only caveat to all of this is the original comment that describe that
`metadata.name` can't be used as it causes crashes. From what I can tell, this
was written in later 2018, and I believe is no longer relevant: the
`metadata.name` field was simply not populated.

Reviewed By: wez

Differential Revision: D21799627

fbshipit-source-id: aee877cc2d5f057944fcd39b1d59f0e97de6315c
2020-06-24 18:59:16 -07:00

41 lines
1.2 KiB
Python

#!/usr/bin/env python3
# Copyright (c) Facebook, Inc. and its affiliates.
#
# This software may be used and distributed according to the terms of the
# GNU General Public License version 2.
import os
import sys
from .lib import testcase
@testcase.eden_repo_test
# pyre-ignore[13]: T62487924
class CasingTest(testcase.EdenRepoTest):
"""Verify that EdenFS behave properly when configured to be case
insensitive and case preserving.
"""
is_case_insensitive: bool
def populate_repo(self) -> None:
self.is_case_insensitive = sys.platform == "win32"
self.repo.write_file("adir1/adir2/a", "Hello!\n")
self.repo.commit("a")
def test_insensitive(self) -> None:
if self.is_case_insensitive:
self.assertEqual(self.read_file("adir1/adir2/A"), "Hello!\n")
def test_case_preserving(self) -> None:
if self.is_case_insensitive:
self.assertEqual(self.read_file("adir1/adir2/A"), "Hello!\n")
self.assertEqual(os.listdir(self.get_path("adir1/adir2")), ["a"])
def test_case_preserving_new_files(self) -> None:
if self.is_case_insensitive:
self.write_file("MixedCaseFile", "content\n")
self.assertIn("MixedCaseFile", os.listdir(self.get_path("")))