sapling/eden/integration/glob_test.py
Wez Furlong cfde0c0717 define paths as binary rather than strings in the thrift interface
Summary:
This prevents `hg status` from blowing up with a UTF-8 decode
error inside the generated thrift code.

Push safety concerns:
* This doesn't change the wire representation of the data
* Existing clients that believe it to be a string will continue to have
  the same behavior
* Buck has its own copy of an older version of the thrift spec, so it will
  continue to work "OK".
* When buck resyncs with our thrift file, some changes will likely be needed
  to convert the byte arrays to strings or paths or whatever is appropriate
  for bucks internal API

Work "OK" above means that clients that currently believe that `string` is
utf-8 encoded will have a runtime error if we ever send them a path that
is not utf-8.  This is the behavior prior to this diff and will continue
to be the behavior for clients (like buck) that have an older version
of the thrift file.

Reviewed By: simpkins

Differential Revision: D9270843

fbshipit-source-id: b01135aec9152aaf5199e1c654ddd7f61c03717e
2018-08-11 01:35:49 -07:00

148 lines
5.2 KiB
Python

#!/usr/bin/env python3
#
# Copyright (c) 2016-present, Facebook, Inc.
# All rights reserved.
#
# This source code is licensed under the BSD-style license found in the
# LICENSE file in the root directory of this source tree. An additional grant
# of patent rights can be found in the PATENTS file in the same directory.
from typing import List, Optional
from facebook.eden.ttypes import EdenError, GlobParams
from .lib import testcase
@testcase.eden_repo_test
class GlobTest(testcase.EdenRepoTest):
def populate_repo(self) -> None:
self.repo.write_file("hello", "hola\n")
self.repo.write_file("adir/file", "foo!\n")
self.repo.write_file("bdir/file", "bar!\n")
self.repo.write_file("bdir/otherfile", "foo!\n")
self.repo.symlink("slink", "hello")
self.repo.write_file("cdir/subdir/new.txt", "and improved")
self.repo.write_file("ddir/notdotfile", "")
self.repo.write_file("ddir/subdir/notdotfile", "")
self.repo.write_file("ddir/subdir/.dotfile", "")
self.repo.write_file("java/com/example/package.html", "")
self.repo.write_file("java/com/example/Example.java", "")
self.repo.write_file("java/com/example/foo/Foo.java", "")
self.repo.write_file("java/com/example/foo/bar/Bar.java", "")
self.repo.write_file("java/com/example/foo/bar/baz/Baz.java", "")
self.repo.commit("Commit 1.")
def setUp(self) -> None:
super().setUp()
self.client = self.get_thrift_client()
self.client.open()
self.addCleanup(self.client.close)
def test_exact_path_component_match(self) -> None:
self.assert_glob(["hello"], [b"hello"])
self.assert_glob(["ddir/subdir/.dotfile"], [b"ddir/subdir/.dotfile"])
def test_wildcard_path_component_match(self) -> None:
self.assert_glob(["hel*"], [b"hello"])
self.assert_glob(["ad*"], [b"adir"])
self.assert_glob(["a*/file"], [b"adir/file"])
def test_no_accidental_substring_match(self) -> None:
self.assert_glob(["hell"], [], msg="No accidental substring match")
def test_match_all_files_in_directory(self) -> None:
self.assert_glob(["bdir/*"], [b"bdir/file", b"bdir/otherfile"])
def test_match_all_files_in_directory_with_dotfile(self) -> None:
self.assert_glob(["ddir/subdir/*"], [b"ddir/subdir/notdotfile"])
def test_overlapping_globs(self) -> None:
self.assert_glob(
["adir/*", "**/file"],
[b"adir/file", b"bdir/file"],
msg="De-duplicate results from multiple globs",
)
def test_recursive_wildcard_prefix(self) -> None:
self.assert_glob(["**/file"], [b"adir/file", b"bdir/file"])
def test_recursive_wildcard_suffix(self) -> None:
self.assert_glob(["adir/**"], [b"adir/file"])
self.assert_glob(["adir/**/*"], [b"adir/file"])
def test_recursive_wildcard_suffix_with_dotfile(self) -> None:
self.assert_glob(
["ddir/**"], [b"ddir/notdotfile", b"ddir/subdir", b"ddir/subdir/notdotfile"]
)
self.assert_glob(
["ddir/**"],
[
b"ddir/subdir",
b"ddir/subdir/.dotfile",
b"ddir/notdotfile",
b"ddir/subdir/notdotfile",
],
include_dotfiles=True,
)
self.assert_glob(
["ddir/**/*"],
[b"ddir/notdotfile", b"ddir/subdir", b"ddir/subdir/notdotfile"],
)
self.assert_glob(
["ddir/**/*"],
[
b"ddir/subdir",
b"ddir/subdir/.dotfile",
b"ddir/notdotfile",
b"ddir/subdir/notdotfile",
],
include_dotfiles=True,
)
def test_qualified_recursive_wildcard(self) -> None:
self.assert_glob(
["java/com/**/*.java"],
[
b"java/com/example/Example.java",
b"java/com/example/foo/Foo.java",
b"java/com/example/foo/bar/Bar.java",
b"java/com/example/foo/bar/baz/Baz.java",
],
)
self.assert_glob(
["java/com/example/*/*.java"], [b"java/com/example/foo/Foo.java"]
)
def test_malformed_query(self) -> None:
with self.assertRaises(EdenError) as ctx:
self.client.glob(self.mount_path_bytes, ["adir["])
self.assertIn("unterminated bracket sequence", str(ctx.exception))
with self.assertRaises(EdenError) as ctx:
self.client.globFiles(GlobParams(self.mount_path_bytes, ["adir["], True))
self.assertIn("unterminated bracket sequence", str(ctx.exception))
def assert_glob(
self,
globs: List[str],
expected_matches: List[bytes],
include_dotfiles: bool = False,
msg: Optional[str] = None,
) -> None:
params = GlobParams(self.mount_path_bytes, globs, include_dotfiles)
self.assertCountEqual(
expected_matches, self.client.globFiles(params).matchingFiles, msg=msg
)
# Also verify behavior of legacy Thrift API.
if include_dotfiles:
self.assertCountEqual(
expected_matches,
self.client.glob(self.mount_path_bytes, globs),
msg=msg,
)