# This file was automatically generated by running:
#
#   scripts/generate_glob_specs.cr
#
# DO NOT EDIT

# These tests are autogenerated from https://raw.githubusercontent.com/oxc-project/fast-glob/refs/heads/main/tests/test.rs
# They are are  collection of tests from bash and micromatch
# https://github.com/micromatch/picomatch/blob/master/test/bash.js.

require "spec"

private def assert_file_matches(pattern, path : String, *, file = __FILE__, line = __LINE__)
  File.match?(pattern, path).should be_true, file: file, line: line
  File.match?(pattern, Path.posix(path)).should be_true, file: file, line: line
  File.match?(pattern, Path.posix(path).to_windows(mappings: false)).should be_true, file: file, line: line
end

private def refute_file_matches(pattern, path : String, *, file = __FILE__, line = __LINE__)
  File.match?(pattern, path).should be_false, file: file, line: line
  File.match?(pattern, Path.posix(path)).should be_false, file: file, line: line
  File.match?(pattern, Path.posix(path).to_windows(mappings: false)).should be_false, file: file, line: line
end

describe "File .match? bash tests" do
  it "webpack" do
    # Match everything
    assert_file_matches "**/*", "foo"

    # Match the end
    assert_file_matches "**/f*", "foo"

    # Match the start
    assert_file_matches "**/*o", "foo"

    # Match the middle
    assert_file_matches "**/f*uck", "firetruck"

    # Don't match without Regexp 'g'
    refute_file_matches "**/uc", "firetruck"

    # Match zero characters
    assert_file_matches "**/f*uck", "fuck"

    # More complex matches
    assert_file_matches "**/*.min.js", "some/jquery.min.js"
    assert_file_matches "**/*.min.*", "some/jquery.min.js"
    assert_file_matches "*/js/*.js", "some/js/jquery.min.js"

    # More complex matches with RegExp 'g' flag (complex regression)
    assert_file_matches "**/*.min.*", "some/jquery.min.js"
    assert_file_matches "**/*.min.js", "some/jquery.min.js"
    assert_file_matches "*/js/*.js", "some/js/jquery.min.js"

    refute_file_matches "\\\\/$^+?.()=!|{},[].*", "\\/$^+?.()=!|{},[].*"

    # Equivalent matches without/with using RegExp 'g'
    refute_file_matches "**/.min.", "some/jquery.min.js"
    assert_file_matches "**/*.min.*", "some/jquery.min.js"
    refute_file_matches "**/.min.", "some/jquery.min.js"

    refute_file_matches "**/min.js", "some/jquery.min.js"
    assert_file_matches "**/*.min.js", "some/jquery.min.js"
    refute_file_matches "**/min.js", "some/jquery.min.js"

    # Match anywhere (globally) using RegExp 'g'
    refute_file_matches "**/min", "some/jquery.min.js"
    refute_file_matches "/js/", "some/js/jquery.min.js"

    refute_file_matches "/js*jq*.js", "some/js/jquery.min.js"

    # Extended mode

    # ?: Match one character, no more and no less
    assert_file_matches "**/f?o", "foo"
    refute_file_matches "**/f?o", "fooo"
    refute_file_matches "**/f?oo", "foo"

    # ?: Match one character with RegExp 'g'
    assert_file_matches "**/f?o", "foo"
    refute_file_matches "**/f?o", "fooo"
    assert_file_matches "**/f?o?", "fooo"
    refute_file_matches "**/?fo", "fooo"
    refute_file_matches "**/f?oo", "foo"
    refute_file_matches "**/foo?", "foo"

    # []: Match a character range
    assert_file_matches "**/fo[oz]", "foo"
    assert_file_matches "**/fo[oz]", "foz"
    refute_file_matches "**/fo[oz]", "fog"

    # []: Match a character range and RegExp 'g' (regression)
    assert_file_matches "**/fo[oz]", "foo"
    assert_file_matches "**/fo[oz]", "foz"
    refute_file_matches "**/fo[oz]", "fog"

    # {}: Match a choice of different substrings
    assert_file_matches "**/foo{bar,baaz}", "foobaaz"
    assert_file_matches "**/foo{bar,baaz}", "foobar"
    refute_file_matches "**/foo{bar,baaz}", "foobuzz"
    assert_file_matches "**/foo{bar,b*z}", "foobuzz"

    # {}: Match a choice of different substrings and RegExp 'g' (regression)
    assert_file_matches "**/foo{bar,baaz}", "foobaaz"
    assert_file_matches "**/foo{bar,baaz}", "foobar"
    refute_file_matches "**/foo{bar,baaz}", "foobuzz"

    # More complex extended matches
    assert_file_matches "?o[oz].b*z.com/{*.js,*.html}", "foo.baaz.com/jquery.min.js"
    assert_file_matches "?o[oz].b*z.com/{*.js,*.html}", "moz.buzz.com/index.html"
    refute_file_matches "?o[oz].b*z.com/{*.js,*.html}", "moz.buzz.com/index.htm"
    refute_file_matches "?o[oz].b*z.com/{*.js,*.html}", "moz.bar.com/index.html"
    refute_file_matches "?o[oz].b*z.com/{*.js,*.html}", "flozz.buzz.com/index.html"

    # More complex extended matches and RegExp 'g' (regression)
    assert_file_matches "?o[oz].b*z.com/{*.js,*.html}", "foo.baaz.com/jquery.min.js"
    assert_file_matches "?o[oz].b*z.com/{*.js,*.html}", "moz.buzz.com/index.html"
    refute_file_matches "?o[oz].b*z.com/{*.js,*.html}", "moz.buzz.com/index.htm"
    refute_file_matches "?o[oz].b*z.com/{*.js,*.html}", "moz.bar.com/index.html"
    refute_file_matches "?o[oz].b*z.com/{*.js,*.html}", "flozz.buzz.com/index.html"

    # globstar
    assert_file_matches "some/**/{*.js,*.html}", "some/bar/jquery.min.js"
    assert_file_matches "some/**/{*.js,*.html}", "some/bar/baz/jquery.min.js"
    assert_file_matches "some/**", "some/bar/baz/jquery.min.js"

    assert_file_matches "\\\\/$^+.()=!|,.*", "\\/$^+.()=!|,.*"

    # globstar specific tests
    assert_file_matches "/foo/*", "/foo/bar.txt"
    assert_file_matches "/foo/**", "/foo/baz.txt"
    assert_file_matches "/foo/**", "/foo/bar/baz.txt"
    assert_file_matches "/foo/*/*.txt", "/foo/bar/baz.txt"
    assert_file_matches "/foo/**/*.txt", "/foo/bar/baz.txt"
    assert_file_matches "/foo/**/*.txt", "/foo/bar/baz/qux.txt"
    assert_file_matches "/foo/**/bar.txt", "/foo/bar.txt"
    assert_file_matches "/foo/**/**/bar.txt", "/foo/bar.txt"
    assert_file_matches "/foo/**/*/baz.txt", "/foo/bar/baz.txt"
    assert_file_matches "/foo/**/*.txt", "/foo/bar.txt"
    assert_file_matches "/foo/**/**/*.txt", "/foo/bar.txt"
    assert_file_matches "/foo/**/*/*.txt", "/foo/bar/baz.txt"
    assert_file_matches "**/*.txt", "/foo/bar/baz/qux.txt"
    assert_file_matches "**/foo.txt", "foo.txt"
    assert_file_matches "**/*.txt", "foo.txt"

    refute_file_matches "/foo/*", "/foo/bar/baz.txt"
    refute_file_matches "/foo/*.txt", "/foo/bar/baz.txt"
    refute_file_matches "/foo/*/*.txt", "/foo/bar/baz/qux.txt"
    refute_file_matches "/foo/*/bar.txt", "/foo/bar.txt"
    refute_file_matches "/foo/*/*/baz.txt", "/foo/bar/baz.txt"
    refute_file_matches "/foo/**.txt", "/foo/bar/baz/qux.txt"
    refute_file_matches "/foo/bar**/*.txt", "/foo/bar/baz/qux.txt"
    refute_file_matches "/foo/bar**", "/foo/bar/baz.txt"
    refute_file_matches "**/.txt", "/foo/bar/baz/qux.txt"
    refute_file_matches "*/*.txt", "/foo/bar/baz/qux.txt"
    refute_file_matches "*/*.txt", "foo.txt"

    refute_file_matches "some/*", "some/bar/baz/jquery.min.js"

    refute_file_matches "some/*", "some/bar/baz/jquery.min.js"
    assert_file_matches "some/**", "some/bar/baz/jquery.min.js"

    assert_file_matches "some/*/*/jquery.min.js", "some/bar/baz/jquery.min.js"
    assert_file_matches "some/**/jquery.min.js", "some/bar/baz/jquery.min.js"
    assert_file_matches "some/*/*/jquery.min.js", "some/bar/baz/jquery.min.js"
    refute_file_matches "some/*/jquery.min.js", "some/bar/baz/jquery.min.js"
    refute_file_matches "some/*/jquery.min.js", "some/bar/baz/jquery.min.js"
  end

  it "basic" do
    assert_file_matches "abc", "abc"
    assert_file_matches "*", "abc"
    assert_file_matches "*", ""
    assert_file_matches "**", ""
    assert_file_matches "*c", "abc"
    refute_file_matches "*b", "abc"
    assert_file_matches "a*", "abc"
    refute_file_matches "b*", "abc"
    assert_file_matches "a*", "a"
    assert_file_matches "*a", "a"
    assert_file_matches "a*b*c*d*e*", "axbxcxdxe"
    assert_file_matches "a*b*c*d*e*", "axbxcxdxexxx"
    assert_file_matches "a*b?c*x", "abxbbxdbxebxczzx"
    refute_file_matches "a*b?c*x", "abxbbxdbxebxczzy"

    assert_file_matches "a/*/test", "a/foo/test"
    refute_file_matches "a/*/test", "a/foo/bar/test"
    assert_file_matches "a/**/test", "a/foo/test"
    assert_file_matches "a/**/test", "a/foo/bar/test"
    assert_file_matches "a/**/b/c", "a/foo/bar/b/c"
    assert_file_matches "a\\*b", "a*b"
    refute_file_matches "a\\*b", "axb"

    assert_file_matches "[abc]", "a"
    assert_file_matches "[abc]", "b"
    assert_file_matches "[abc]", "c"
    refute_file_matches "[abc]", "d"
    assert_file_matches "x[abc]x", "xax"
    assert_file_matches "x[abc]x", "xbx"
    assert_file_matches "x[abc]x", "xcx"
    refute_file_matches "x[abc]x", "xdx"
    refute_file_matches "x[abc]x", "xay"
    assert_file_matches "[?]", "?"
    refute_file_matches "[?]", "a"
    assert_file_matches "[*]", "*"
    refute_file_matches "[*]", "a"

    assert_file_matches "[a-cx]", "a"
    assert_file_matches "[a-cx]", "b"
    assert_file_matches "[a-cx]", "c"
    refute_file_matches "[a-cx]", "d"
    assert_file_matches "[a-cx]", "x"

    refute_file_matches "[^abc]", "a"
    refute_file_matches "[^abc]", "b"
    refute_file_matches "[^abc]", "c"
    assert_file_matches "[^abc]", "d"
    assert_file_matches "[!abc]", "a" # unsupported
    assert_file_matches "[!abc]", "b" # unsupported
    assert_file_matches "[!abc]", "c" # unsupported
    refute_file_matches "[!abc]", "d" # unsupported
    assert_file_matches "[!abc]", "!" # unsupported
    assert_file_matches "[\\!]", "!"

    assert_file_matches "a*b*[cy]*d*e*", "axbxcxdxexxx"
    assert_file_matches "a*b*[cy]*d*e*", "axbxyxdxexxx"
    assert_file_matches "a*b*[cy]*d*e*", "axbxxxyxdxexxx"

    assert_file_matches "test.{jpg,png}", "test.jpg"
    assert_file_matches "test.{jpg,png}", "test.png"
    assert_file_matches "test.{j*g,p*g}", "test.jpg"
    assert_file_matches "test.{j*g,p*g}", "test.jpxxxg"
    assert_file_matches "test.{j*g,p*g}", "test.jxg"
    refute_file_matches "test.{j*g,p*g}", "test.jnt"

    assert_file_matches "test.{j*g,j*c}", "test.jnc"
    assert_file_matches "test.{jpg,p*g}", "test.png"
    assert_file_matches "test.{jpg,p*g}", "test.pxg"
    refute_file_matches "test.{jpg,p*g}", "test.pnt"
    assert_file_matches "test.{jpeg,png}", "test.jpeg"
    refute_file_matches "test.{jpeg,png}", "test.jpg"
    assert_file_matches "test.{jpeg,png}", "test.png"
    assert_file_matches "test.{jp\\,g,png}", "test.jp,g"
    refute_file_matches "test.{jp\\,g,png}", "test.jxg"
    assert_file_matches "test/{foo,bar}/baz", "test/foo/baz"
    assert_file_matches "test/{foo,bar}/baz", "test/bar/baz"
    refute_file_matches "test/{foo,bar}/baz", "test/baz/baz"
    assert_file_matches "test/{foo*,bar*}/baz", "test/foooooo/baz"
    assert_file_matches "test/{foo*,bar*}/baz", "test/barrrrr/baz"
    assert_file_matches "test/{*foo,*bar}/baz", "test/xxxxfoo/baz"
    assert_file_matches "test/{*foo,*bar}/baz", "test/xxxxbar/baz"
    assert_file_matches "test/{foo/**,bar}/baz", "test/bar/baz"
    refute_file_matches "test/{foo/**,bar}/baz", "test/bar/test/baz"

    refute_file_matches "*.txt", "some/big/path/to/the/needle.txt"
    assert_file_matches(
      "some/**/needle.{js,tsx,mdx,ts,jsx,txt}",
      "some/a/bigger/path/to/the/crazy/needle.txt"
    )
    assert_file_matches(
      "some/**/{a,b,c}/**/needle.txt",
      "some/foo/a/bigger/path/to/the/crazy/needle.txt"
    )
    refute_file_matches(
      "some/**/{a,b,c}/**/needle.txt",
      "some/foo/d/bigger/path/to/the/crazy/needle.txt"
    )

    assert_file_matches "a/{a{a,b},b}", "a/aa"
    assert_file_matches "a/{a{a,b},b}", "a/ab"
    refute_file_matches "a/{a{a,b},b}", "a/ac"
    assert_file_matches "a/{a{a,b},b}", "a/b"
    refute_file_matches "a/{a{a,b},b}", "a/c"
    assert_file_matches "a/{b,c[}]*}", "a/b"
    assert_file_matches "a/{b,c[}]*}", "a/c}xx"

    assert_file_matches "/**/*a", "/a/a"
    assert_file_matches "**/*.js", "a/b.c/c.js"
    assert_file_matches "**/**/*.js", "a/b.c/c.js"
    assert_file_matches "a/**/*.d", "a/b/c.d"
    assert_file_matches "a/**/*.d", "a/.b/c.d"

    assert_file_matches "**/*/**", "a/b/c"
    assert_file_matches "**/*/c.js", "a/b/c.js"
  end

  # The below tests are based on Bash and micromatch.
  # https://github.com/micromatch/picomatch/blob/master/test/bash.js
  # Converted using the following find and replace regex:
  # find: assert\(([!])?isMatch\('(.*?)', ['"](.*?)['"]\)\);
  # replace: assert!($1glob_match("$3", "$2")

  it "bash" do
    refute_file_matches "a*", "*"
    refute_file_matches "a*", "**"
    refute_file_matches "a*", "\\*"
    refute_file_matches "a*", "a/*"
    refute_file_matches "a*", "b"
    refute_file_matches "a*", "bc"
    refute_file_matches "a*", "bcd"
    refute_file_matches "a*", "bdir/"
    refute_file_matches "a*", "Beware"
    assert_file_matches "a*", "a"
    assert_file_matches "a*", "ab"
    assert_file_matches "a*", "abc"

    refute_file_matches "\\a*", "*"
    refute_file_matches "\\a*", "**"
    refute_file_matches "\\a*", "\\*"

    assert_file_matches "\\a*", "a"
    refute_file_matches "\\a*", "a/*"
    assert_file_matches "\\a*", "abc"
    assert_file_matches "\\a*", "abd"
    assert_file_matches "\\a*", "abe"
    refute_file_matches "\\a*", "b"
    refute_file_matches "\\a*", "bb"
    refute_file_matches "\\a*", "bcd"
    refute_file_matches "\\a*", "bdir/"
    refute_file_matches "\\a*", "Beware"
    refute_file_matches "\\a*", "c"
    refute_file_matches "\\a*", "ca"
    refute_file_matches "\\a*", "cb"
    refute_file_matches "\\a*", "d"
    refute_file_matches "\\a*", "dd"
    refute_file_matches "\\a*", "de"
  end

  it "bash_directories" do
    refute_file_matches "b*/", "*"
    refute_file_matches "b*/", "**"
    refute_file_matches "b*/", "\\*"
    refute_file_matches "b*/", "a"
    refute_file_matches "b*/", "a/*"
    refute_file_matches "b*/", "abc"
    refute_file_matches "b*/", "abd"
    refute_file_matches "b*/", "abe"
    refute_file_matches "b*/", "b"
    refute_file_matches "b*/", "bb"
    refute_file_matches "b*/", "bcd"
    assert_file_matches "b*/", "bdir/"
    refute_file_matches "b*/", "Beware"
    refute_file_matches "b*/", "c"
    refute_file_matches "b*/", "ca"
    refute_file_matches "b*/", "cb"
    refute_file_matches "b*/", "d"
    refute_file_matches "b*/", "dd"
    refute_file_matches "b*/", "de"
  end

  it "bash_escaping" do
    refute_file_matches "\\^", "*"
    refute_file_matches "\\^", "**"
    refute_file_matches "\\^", "\\*"
    refute_file_matches "\\^", "a"
    refute_file_matches "\\^", "a/*"
    refute_file_matches "\\^", "abc"
    refute_file_matches "\\^", "abd"
    refute_file_matches "\\^", "abe"
    refute_file_matches "\\^", "b"
    refute_file_matches "\\^", "bb"
    refute_file_matches "\\^", "bcd"
    refute_file_matches "\\^", "bdir/"
    refute_file_matches "\\^", "Beware"
    refute_file_matches "\\^", "c"
    refute_file_matches "\\^", "ca"
    refute_file_matches "\\^", "cb"
    refute_file_matches "\\^", "d"
    refute_file_matches "\\^", "dd"
    refute_file_matches "\\^", "de"

    assert_file_matches "\\*", "*"
    # assert_file_matches "\\*", "\\*"
    refute_file_matches "\\*", "**"
    refute_file_matches "\\*", "a"
    refute_file_matches "\\*", "a/*"
    refute_file_matches "\\*", "abc"
    refute_file_matches "\\*", "abd"
    refute_file_matches "\\*", "abe"
    refute_file_matches "\\*", "b"
    refute_file_matches "\\*", "bb"
    refute_file_matches "\\*", "bcd"
    refute_file_matches "\\*", "bdir/"
    refute_file_matches "\\*", "Beware"
    refute_file_matches "\\*", "c"
    refute_file_matches "\\*", "ca"
    refute_file_matches "\\*", "cb"
    refute_file_matches "\\*", "d"
    refute_file_matches "\\*", "dd"
    refute_file_matches "\\*", "de"

    refute_file_matches "a\\*", "*"
    refute_file_matches "a\\*", "**"
    refute_file_matches "a\\*", "\\*"
    refute_file_matches "a\\*", "a"
    refute_file_matches "a\\*", "a/*"
    refute_file_matches "a\\*", "abc"
    refute_file_matches "a\\*", "abd"
    refute_file_matches "a\\*", "abe"
    refute_file_matches "a\\*", "b"
    refute_file_matches "a\\*", "bb"
    refute_file_matches "a\\*", "bcd"
    refute_file_matches "a\\*", "bdir/"
    refute_file_matches "a\\*", "Beware"
    refute_file_matches "a\\*", "c"
    refute_file_matches "a\\*", "ca"
    refute_file_matches "a\\*", "cb"
    refute_file_matches "a\\*", "d"
    refute_file_matches "a\\*", "dd"
    refute_file_matches "a\\*", "de"

    assert_file_matches "*q*", "aqa"
    assert_file_matches "*q*", "aaqaa"
    refute_file_matches "*q*", "*"
    refute_file_matches "*q*", "**"
    refute_file_matches "*q*", "\\*"
    refute_file_matches "*q*", "a"
    refute_file_matches "*q*", "a/*"
    refute_file_matches "*q*", "abc"
    refute_file_matches "*q*", "abd"
    refute_file_matches "*q*", "abe"
    refute_file_matches "*q*", "b"
    refute_file_matches "*q*", "bb"
    refute_file_matches "*q*", "bcd"
    refute_file_matches "*q*", "bdir/"
    refute_file_matches "*q*", "Beware"
    refute_file_matches "*q*", "c"
    refute_file_matches "*q*", "ca"
    refute_file_matches "*q*", "cb"
    refute_file_matches "*q*", "d"
    refute_file_matches "*q*", "dd"
    refute_file_matches "*q*", "de"

    assert_file_matches "\\**", "*"
    assert_file_matches "\\**", "**"
    refute_file_matches "\\**", "\\*"
    refute_file_matches "\\**", "a"
    refute_file_matches "\\**", "a/*"
    refute_file_matches "\\**", "abc"
    refute_file_matches "\\**", "abd"
    refute_file_matches "\\**", "abe"
    refute_file_matches "\\**", "b"
    refute_file_matches "\\**", "bb"
    refute_file_matches "\\**", "bcd"
    refute_file_matches "\\**", "bdir/"
    refute_file_matches "\\**", "Beware"
    refute_file_matches "\\**", "c"
    refute_file_matches "\\**", "ca"
    refute_file_matches "\\**", "cb"
    refute_file_matches "\\**", "d"
    refute_file_matches "\\**", "dd"
    refute_file_matches "\\**", "de"
  end

  it "bash_classes" do
    refute_file_matches "a*[^c]", "*"
    refute_file_matches "a*[^c]", "**"
    refute_file_matches "a*[^c]", "\\*"
    refute_file_matches "a*[^c]", "a"
    refute_file_matches "a*[^c]", "a/*"
    refute_file_matches "a*[^c]", "abc"
    assert_file_matches "a*[^c]", "abd"
    assert_file_matches "a*[^c]", "abe"
    refute_file_matches "a*[^c]", "b"
    refute_file_matches "a*[^c]", "bb"
    refute_file_matches "a*[^c]", "bcd"
    refute_file_matches "a*[^c]", "bdir/"
    refute_file_matches "a*[^c]", "Beware"
    refute_file_matches "a*[^c]", "c"
    refute_file_matches "a*[^c]", "ca"
    refute_file_matches "a*[^c]", "cb"
    refute_file_matches "a*[^c]", "d"
    refute_file_matches "a*[^c]", "dd"
    refute_file_matches "a*[^c]", "de"
    refute_file_matches "a*[^c]", "baz"
    refute_file_matches "a*[^c]", "bzz"
    refute_file_matches "a*[^c]", "BZZ"
    refute_file_matches "a*[^c]", "beware"
    refute_file_matches "a*[^c]", "BewAre"

    assert_file_matches "a[X-]b", "a-b"
    assert_file_matches "a[X-]b", "aXb"

    refute_file_matches "[a-y]*[^c]", "*"
    assert_file_matches "[a-y]*[^c]", "a*"
    refute_file_matches "[a-y]*[^c]", "**"
    refute_file_matches "[a-y]*[^c]", "\\*"
    refute_file_matches "[a-y]*[^c]", "a"
    assert_file_matches "[a-y]*[^c]", "a123b"
    refute_file_matches "[a-y]*[^c]", "a123c"
    assert_file_matches "[a-y]*[^c]", "ab"
    refute_file_matches "[a-y]*[^c]", "a/*"
    refute_file_matches "[a-y]*[^c]", "abc"
    assert_file_matches "[a-y]*[^c]", "abd"
    assert_file_matches "[a-y]*[^c]", "abe"
    refute_file_matches "[a-y]*[^c]", "b"
    assert_file_matches "[a-y]*[^c]", "bd"
    assert_file_matches "[a-y]*[^c]", "bb"
    assert_file_matches "[a-y]*[^c]", "bcd"
    assert_file_matches "[a-y]*[^c]", "bdir/"
    refute_file_matches "[a-y]*[^c]", "Beware"
    refute_file_matches "[a-y]*[^c]", "c"
    assert_file_matches "[a-y]*[^c]", "ca"
    assert_file_matches "[a-y]*[^c]", "cb"
    refute_file_matches "[a-y]*[^c]", "d"
    assert_file_matches "[a-y]*[^c]", "dd"
    assert_file_matches "[a-y]*[^c]", "de"
    assert_file_matches "[a-y]*[^c]", "baz"
    assert_file_matches "[a-y]*[^c]", "bzz"
    # assert(!isMatch('bzz', '[a-y]*[^c]', { regex: true })
    refute_file_matches "[a-y]*[^c]", "BZZ"
    assert_file_matches "[a-y]*[^c]", "beware"
    refute_file_matches "[a-y]*[^c]", "BewAre"

    assert_file_matches "a\\*b/*", "a*b/ooo"
    assert_file_matches "a\\*?/*", "a*b/ooo"

    refute_file_matches "a[b]c", "*"
    refute_file_matches "a[b]c", "**"
    refute_file_matches "a[b]c", "\\*"
    refute_file_matches "a[b]c", "a"
    refute_file_matches "a[b]c", "a/*"
    assert_file_matches "a[b]c", "abc"
    refute_file_matches "a[b]c", "abd"
    refute_file_matches "a[b]c", "abe"
    refute_file_matches "a[b]c", "b"
    refute_file_matches "a[b]c", "bb"
    refute_file_matches "a[b]c", "bcd"
    refute_file_matches "a[b]c", "bdir/"
    refute_file_matches "a[b]c", "Beware"
    refute_file_matches "a[b]c", "c"
    refute_file_matches "a[b]c", "ca"
    refute_file_matches "a[b]c", "cb"
    refute_file_matches "a[b]c", "d"
    refute_file_matches "a[b]c", "dd"
    refute_file_matches "a[b]c", "de"
    refute_file_matches "a[b]c", "baz"
    refute_file_matches "a[b]c", "bzz"
    refute_file_matches "a[b]c", "BZZ"
    refute_file_matches "a[b]c", "beware"
    refute_file_matches "a[b]c", "BewAre"

    refute_file_matches "a[\"b\"]c", "*"
    refute_file_matches "a[\"b\"]c", "**"
    refute_file_matches "a[\"b\"]c", "\\*"
    refute_file_matches "a[\"b\"]c", "a"
    refute_file_matches "a[\"b\"]c", "a/*"
    assert_file_matches "a[\"b\"]c", "abc"
    refute_file_matches "a[\"b\"]c", "abd"
    refute_file_matches "a[\"b\"]c", "abe"
    refute_file_matches "a[\"b\"]c", "b"
    refute_file_matches "a[\"b\"]c", "bb"
    refute_file_matches "a[\"b\"]c", "bcd"
    refute_file_matches "a[\"b\"]c", "bdir/"
    refute_file_matches "a[\"b\"]c", "Beware"
    refute_file_matches "a[\"b\"]c", "c"
    refute_file_matches "a[\"b\"]c", "ca"
    refute_file_matches "a[\"b\"]c", "cb"
    refute_file_matches "a[\"b\"]c", "d"
    refute_file_matches "a[\"b\"]c", "dd"
    refute_file_matches "a[\"b\"]c", "de"
    refute_file_matches "a[\"b\"]c", "baz"
    refute_file_matches "a[\"b\"]c", "bzz"
    refute_file_matches "a[\"b\"]c", "BZZ"
    refute_file_matches "a[\"b\"]c", "beware"
    refute_file_matches "a[\"b\"]c", "BewAre"

    refute_file_matches "a[\\\\b]c", "*"
    refute_file_matches "a[\\\\b]c", "**"
    refute_file_matches "a[\\\\b]c", "\\*"
    refute_file_matches "a[\\\\b]c", "a"
    refute_file_matches "a[\\\\b]c", "a/*"
    assert_file_matches "a[\\\\b]c", "abc"
    refute_file_matches "a[\\\\b]c", "abd"
    refute_file_matches "a[\\\\b]c", "abe"
    refute_file_matches "a[\\\\b]c", "b"
    refute_file_matches "a[\\\\b]c", "bb"
    refute_file_matches "a[\\\\b]c", "bcd"
    refute_file_matches "a[\\\\b]c", "bdir/"
    refute_file_matches "a[\\\\b]c", "Beware"
    refute_file_matches "a[\\\\b]c", "c"
    refute_file_matches "a[\\\\b]c", "ca"
    refute_file_matches "a[\\\\b]c", "cb"
    refute_file_matches "a[\\\\b]c", "d"
    refute_file_matches "a[\\\\b]c", "dd"
    refute_file_matches "a[\\\\b]c", "de"
    refute_file_matches "a[\\\\b]c", "baz"
    refute_file_matches "a[\\\\b]c", "bzz"
    refute_file_matches "a[\\\\b]c", "BZZ"
    refute_file_matches "a[\\\\b]c", "beware"
    refute_file_matches "a[\\\\b]c", "BewAre"

    refute_file_matches "a[\\b]c", "*"
    refute_file_matches "a[\\b]c", "**"
    refute_file_matches "a[\\b]c", "\\*"
    refute_file_matches "a[\\b]c", "a"
    refute_file_matches "a[\\b]c", "a/*"
    refute_file_matches "a[\\b]c", "abc"
    refute_file_matches "a[\\b]c", "abd"
    refute_file_matches "a[\\b]c", "abe"
    refute_file_matches "a[\\b]c", "b"
    refute_file_matches "a[\\b]c", "bb"
    refute_file_matches "a[\\b]c", "bcd"
    refute_file_matches "a[\\b]c", "bdir/"
    refute_file_matches "a[\\b]c", "Beware"
    refute_file_matches "a[\\b]c", "c"
    refute_file_matches "a[\\b]c", "ca"
    refute_file_matches "a[\\b]c", "cb"
    refute_file_matches "a[\\b]c", "d"
    refute_file_matches "a[\\b]c", "dd"
    refute_file_matches "a[\\b]c", "de"
    refute_file_matches "a[\\b]c", "baz"
    refute_file_matches "a[\\b]c", "bzz"
    refute_file_matches "a[\\b]c", "BZZ"
    refute_file_matches "a[\\b]c", "beware"
    refute_file_matches "a[\\b]c", "BewAre"

    refute_file_matches "a[b-d]c", "*"
    refute_file_matches "a[b-d]c", "**"
    refute_file_matches "a[b-d]c", "\\*"
    refute_file_matches "a[b-d]c", "a"
    refute_file_matches "a[b-d]c", "a/*"
    assert_file_matches "a[b-d]c", "abc"
    refute_file_matches "a[b-d]c", "abd"
    refute_file_matches "a[b-d]c", "abe"
    refute_file_matches "a[b-d]c", "b"
    refute_file_matches "a[b-d]c", "bb"
    refute_file_matches "a[b-d]c", "bcd"
    refute_file_matches "a[b-d]c", "bdir/"
    refute_file_matches "a[b-d]c", "Beware"
    refute_file_matches "a[b-d]c", "c"
    refute_file_matches "a[b-d]c", "ca"
    refute_file_matches "a[b-d]c", "cb"
    refute_file_matches "a[b-d]c", "d"
    refute_file_matches "a[b-d]c", "dd"
    refute_file_matches "a[b-d]c", "de"
    refute_file_matches "a[b-d]c", "baz"
    refute_file_matches "a[b-d]c", "bzz"
    refute_file_matches "a[b-d]c", "BZZ"
    refute_file_matches "a[b-d]c", "beware"
    refute_file_matches "a[b-d]c", "BewAre"

    refute_file_matches "a?c", "*"
    refute_file_matches "a?c", "**"
    refute_file_matches "a?c", "\\*"
    refute_file_matches "a?c", "a"
    refute_file_matches "a?c", "a/*"
    assert_file_matches "a?c", "abc"
    refute_file_matches "a?c", "abd"
    refute_file_matches "a?c", "abe"
    refute_file_matches "a?c", "b"
    refute_file_matches "a?c", "bb"
    refute_file_matches "a?c", "bcd"
    refute_file_matches "a?c", "bdir/"
    refute_file_matches "a?c", "Beware"
    refute_file_matches "a?c", "c"
    refute_file_matches "a?c", "ca"
    refute_file_matches "a?c", "cb"
    refute_file_matches "a?c", "d"
    refute_file_matches "a?c", "dd"
    refute_file_matches "a?c", "de"
    refute_file_matches "a?c", "baz"
    refute_file_matches "a?c", "bzz"
    refute_file_matches "a?c", "BZZ"
    refute_file_matches "a?c", "beware"
    refute_file_matches "a?c", "BewAre"

    assert_file_matches "*/man*/bash.*", "man/man1/bash.1"

    assert_file_matches "[^a-c]*", "*"
    assert_file_matches "[^a-c]*", "**"
    refute_file_matches "[^a-c]*", "a"
    refute_file_matches "[^a-c]*", "a/*"
    refute_file_matches "[^a-c]*", "abc"
    refute_file_matches "[^a-c]*", "abd"
    refute_file_matches "[^a-c]*", "abe"
    refute_file_matches "[^a-c]*", "b"
    refute_file_matches "[^a-c]*", "bb"
    refute_file_matches "[^a-c]*", "bcd"
    refute_file_matches "[^a-c]*", "bdir/"
    assert_file_matches "[^a-c]*", "Beware"
    refute_file_matches "[^a-c]*", "c"
    refute_file_matches "[^a-c]*", "ca"
    refute_file_matches "[^a-c]*", "cb"
    assert_file_matches "[^a-c]*", "d"
    assert_file_matches "[^a-c]*", "dd"
    assert_file_matches "[^a-c]*", "de"
    refute_file_matches "[^a-c]*", "baz"
    refute_file_matches "[^a-c]*", "bzz"
    assert_file_matches "[^a-c]*", "BZZ"
    refute_file_matches "[^a-c]*", "beware"
    assert_file_matches "[^a-c]*", "BewAre"
  end

  it "bash_wildmatch" do
    refute_file_matches "a[]-]b", "aab"
    refute_file_matches "[ten]", "ten"
    assert_file_matches "]", "]"
    assert_file_matches "a[]-]b", "a-b"
    assert_file_matches "a[]-]b", "a]b"
    assert_file_matches "a[]]b", "a]b"
    assert_file_matches "a[\\]a\\-]b", "aab"
    assert_file_matches "t[a-g]n", "ten"
    assert_file_matches "t[^a-g]n", "ton"
  end

  it "bash_slashmatch" do
    # refute_file_matches "f[^eiu][^eiu][^eiu][^eiu][^eiu]r", "foo/bar"
    assert_file_matches "foo[/]bar", "foo/bar"
    assert_file_matches "f[^eiu][^eiu][^eiu][^eiu][^eiu]r", "foo-bar"
  end

  it "bash_extra_stars" do
    refute_file_matches "a**c", "bbc"
    assert_file_matches "a**c", "abc"
    refute_file_matches "a**c", "bbd"

    refute_file_matches "a***c", "bbc"
    assert_file_matches "a***c", "abc"
    refute_file_matches "a***c", "bbd"

    refute_file_matches "a*****?c", "bbc"
    assert_file_matches "a*****?c", "abc"
    refute_file_matches "a*****?c", "bbc"

    assert_file_matches "?*****??", "bbc"
    assert_file_matches "?*****??", "abc"

    assert_file_matches "*****??", "bbc"
    assert_file_matches "*****??", "abc"

    assert_file_matches "?*****?c", "bbc"
    assert_file_matches "?*****?c", "abc"

    assert_file_matches "?***?****c", "bbc"
    assert_file_matches "?***?****c", "abc"
    refute_file_matches "?***?****c", "bbd"

    assert_file_matches "?***?****?", "bbc"
    assert_file_matches "?***?****?", "abc"

    assert_file_matches "?***?****", "bbc"
    assert_file_matches "?***?****", "abc"

    assert_file_matches "*******c", "bbc"
    assert_file_matches "*******c", "abc"

    assert_file_matches "*******?", "bbc"
    assert_file_matches "*******?", "abc"

    assert_file_matches "a*cd**?**??k", "abcdecdhjk"
    assert_file_matches "a**?**cd**?**??k", "abcdecdhjk"
    assert_file_matches "a**?**cd**?**??k***", "abcdecdhjk"
    assert_file_matches "a**?**cd**?**??***k", "abcdecdhjk"
    assert_file_matches "a**?**cd**?**??***k**", "abcdecdhjk"
    assert_file_matches "a****c**?**??*****", "abcdecdhjk"
  end

  it "stars" do
    refute_file_matches "*.js", "a/b/c/z.js"
    refute_file_matches "*.js", "a/b/z.js"
    refute_file_matches "*.js", "a/z.js"
    assert_file_matches "*.js", "z.js"

    # refute_file_matches "*/*", "a/.ab"
    # refute_file_matches "*", ".ab"

    assert_file_matches "z*.js", "z.js"
    assert_file_matches "*/*", "a/z"
    assert_file_matches "*/z*.js", "a/z.js"
    assert_file_matches "a/z*.js", "a/z.js"

    assert_file_matches "*", "ab"
    assert_file_matches "*", "abc"

    refute_file_matches "f*", "bar"
    refute_file_matches "*r", "foo"
    refute_file_matches "b*", "foo"
    refute_file_matches "*", "foo/bar"
    assert_file_matches "*c", "abc"
    assert_file_matches "a*", "abc"
    assert_file_matches "a*c", "abc"
    assert_file_matches "*r", "bar"
    assert_file_matches "b*", "bar"
    assert_file_matches "f*", "foo"

    assert_file_matches "*abc*", "one abc two"
    assert_file_matches "a*b", "a         b"

    refute_file_matches "*a*", "foo"
    assert_file_matches "*a*", "bar"
    assert_file_matches "*abc*", "oneabctwo"
    refute_file_matches "*-bc-*", "a-b.c-d"
    assert_file_matches "*-*.*-*", "a-b.c-d"
    assert_file_matches "*-b*c-*", "a-b.c-d"
    assert_file_matches "*-b.c-*", "a-b.c-d"
    assert_file_matches "*.*", "a-b.c-d"
    assert_file_matches "*.*-*", "a-b.c-d"
    assert_file_matches "*.*-d", "a-b.c-d"
    assert_file_matches "*.c-*", "a-b.c-d"
    assert_file_matches "*b.*d", "a-b.c-d"
    assert_file_matches "a*.c*", "a-b.c-d"
    assert_file_matches "a-*.*-d", "a-b.c-d"
    assert_file_matches "*.*", "a.b"
    assert_file_matches "*.b", "a.b"
    assert_file_matches "a.*", "a.b"
    assert_file_matches "a.b", "a.b"

    refute_file_matches "**-bc-**", "a-b.c-d"
    assert_file_matches "**-**.**-**", "a-b.c-d"
    assert_file_matches "**-b**c-**", "a-b.c-d"
    assert_file_matches "**-b.c-**", "a-b.c-d"
    assert_file_matches "**.**", "a-b.c-d"
    assert_file_matches "**.**-**", "a-b.c-d"
    assert_file_matches "**.**-d", "a-b.c-d"
    assert_file_matches "**.c-**", "a-b.c-d"
    assert_file_matches "**b.**d", "a-b.c-d"
    assert_file_matches "a**.c**", "a-b.c-d"
    assert_file_matches "a-**.**-d", "a-b.c-d"
    assert_file_matches "**.**", "a.b"
    assert_file_matches "**.b", "a.b"
    assert_file_matches "a.**", "a.b"
    assert_file_matches "a.b", "a.b"

    assert_file_matches "*/*", "/ab"
    assert_file_matches ".", "."
    refute_file_matches "a/", "a/.b"
    assert_file_matches "/*", "/ab"
    assert_file_matches "/??", "/ab"
    assert_file_matches "/?b", "/ab"
    assert_file_matches "/*", "/cd"
    assert_file_matches "a", "a"
    assert_file_matches "a/.*", "a/.b"
    assert_file_matches "?/?", "a/b"
    assert_file_matches "a/**/j/**/z/*.md", "a/b/c/d/e/j/n/p/o/z/c.md"
    assert_file_matches "a/**/z/*.md", "a/b/c/d/e/z/c.md"
    assert_file_matches "a/b/c/*.md", "a/b/c/xyz.md"
    assert_file_matches "a/*/z/.a", "a/b/z/.a"
    refute_file_matches "bz", "a/b/z/.a"
    assert_file_matches "a/**/c/*.md", "a/bb.bb/aa/b.b/aa/c/xyz.md"
    assert_file_matches "a/**/c/*.md", "a/bb.bb/aa/bb/aa/c/xyz.md"
    assert_file_matches "a/*/c/*.md", "a/bb.bb/c/xyz.md"
    assert_file_matches "a/*/c/*.md", "a/bb/c/xyz.md"
    assert_file_matches "a/*/c/*.md", "a/bbbb/c/xyz.md"
    assert_file_matches "*", "aaa"
    assert_file_matches "*", "ab"
    assert_file_matches "ab", "ab"

    refute_file_matches "*/*/*", "aaa"
    refute_file_matches "*/*/*", "aaa/bb/aa/rr"
    refute_file_matches "aaa*", "aaa/bba/ccc"
    # refute_file_matches "aaa**", "aaa/bba/ccc"
    refute_file_matches "aaa/*", "aaa/bba/ccc"
    refute_file_matches "aaa/*ccc", "aaa/bba/ccc"
    refute_file_matches "aaa/*z", "aaa/bba/ccc"
    refute_file_matches "*/*/*", "aaa/bbb"
    refute_file_matches "*/*jk*/*i", "ab/zzz/ejkl/hi"
    assert_file_matches "*/*/*", "aaa/bba/ccc"
    assert_file_matches "aaa/**", "aaa/bba/ccc"
    assert_file_matches "aaa/*", "aaa/bbb"
    assert_file_matches "*/*z*/*/*i", "ab/zzz/ejkl/hi"
    assert_file_matches "*j*i", "abzzzejklhi"

    assert_file_matches "*", "a"
    assert_file_matches "*", "b"
    refute_file_matches "*", "a/a"
    refute_file_matches "*", "a/a/a"
    refute_file_matches "*", "a/a/b"
    refute_file_matches "*", "a/a/a/a"
    refute_file_matches "*", "a/a/a/a/a"

    refute_file_matches "*/*", "a"
    assert_file_matches "*/*", "a/a"
    refute_file_matches "*/*", "a/a/a"

    refute_file_matches "*/*/*", "a"
    refute_file_matches "*/*/*", "a/a"
    assert_file_matches "*/*/*", "a/a/a"
    refute_file_matches "*/*/*", "a/a/a/a"

    refute_file_matches "*/*/*/*", "a"
    refute_file_matches "*/*/*/*", "a/a"
    refute_file_matches "*/*/*/*", "a/a/a"
    assert_file_matches "*/*/*/*", "a/a/a/a"
    refute_file_matches "*/*/*/*", "a/a/a/a/a"

    refute_file_matches "*/*/*/*/*", "a"
    refute_file_matches "*/*/*/*/*", "a/a"
    refute_file_matches "*/*/*/*/*", "a/a/a"
    refute_file_matches "*/*/*/*/*", "a/a/b"
    refute_file_matches "*/*/*/*/*", "a/a/a/a"
    assert_file_matches "*/*/*/*/*", "a/a/a/a/a"
    refute_file_matches "*/*/*/*/*", "a/a/a/a/a/a"

    refute_file_matches "a/*", "a"
    assert_file_matches "a/*", "a/a"
    refute_file_matches "a/*", "a/a/a"
    refute_file_matches "a/*", "a/a/a/a"
    refute_file_matches "a/*", "a/a/a/a/a"

    refute_file_matches "a/*/*", "a"
    refute_file_matches "a/*/*", "a/a"
    assert_file_matches "a/*/*", "a/a/a"
    refute_file_matches "a/*/*", "b/a/a"
    refute_file_matches "a/*/*", "a/a/a/a"
    refute_file_matches "a/*/*", "a/a/a/a/a"

    refute_file_matches "a/*/*/*", "a"
    refute_file_matches "a/*/*/*", "a/a"
    refute_file_matches "a/*/*/*", "a/a/a"
    assert_file_matches "a/*/*/*", "a/a/a/a"
    refute_file_matches "a/*/*/*", "a/a/a/a/a"

    refute_file_matches "a/*/*/*/*", "a"
    refute_file_matches "a/*/*/*/*", "a/a"
    refute_file_matches "a/*/*/*/*", "a/a/a"
    refute_file_matches "a/*/*/*/*", "a/a/b"
    refute_file_matches "a/*/*/*/*", "a/a/a/a"
    assert_file_matches "a/*/*/*/*", "a/a/a/a/a"

    refute_file_matches "a/*/a", "a"
    refute_file_matches "a/*/a", "a/a"
    assert_file_matches "a/*/a", "a/a/a"
    refute_file_matches "a/*/a", "a/a/b"
    refute_file_matches "a/*/a", "a/a/a/a"
    refute_file_matches "a/*/a", "a/a/a/a/a"

    refute_file_matches "a/*/b", "a"
    refute_file_matches "a/*/b", "a/a"
    refute_file_matches "a/*/b", "a/a/a"
    assert_file_matches "a/*/b", "a/a/b"
    refute_file_matches "a/*/b", "a/a/a/a"
    refute_file_matches "a/*/b", "a/a/a/a/a"

    refute_file_matches "*/**/a", "a"
    refute_file_matches "*/**/a", "a/a/b"
    assert_file_matches "*/**/a", "a/a"
    assert_file_matches "*/**/a", "a/a/a"
    assert_file_matches "*/**/a", "a/a/a/a"
    assert_file_matches "*/**/a", "a/a/a/a/a"

    refute_file_matches "*/", "a"
    refute_file_matches "*/*", "a"
    refute_file_matches "a/*", "a"
    # refute_file_matches "*/*", "a/"
    # refute_file_matches "a/*", "a/"
    refute_file_matches "*", "a/a"
    refute_file_matches "*/", "a/a"
    refute_file_matches "*/", "a/x/y"
    refute_file_matches "*/*", "a/x/y"
    refute_file_matches "a/*", "a/x/y"
    # assert_file_matches "*", "a/"
    assert_file_matches "*", "a"
    assert_file_matches "*/", "a/"
    assert_file_matches "*{,/}", "a/"
    assert_file_matches "*/*", "a/a"
    assert_file_matches "a/*", "a/a"

    refute_file_matches "a/**/*.txt", "a.txt"
    assert_file_matches "a/**/*.txt", "a/x/y.txt"
    refute_file_matches "a/**/*.txt", "a/x/y/z"

    refute_file_matches "a/*.txt", "a.txt"
    assert_file_matches "a/*.txt", "a/b.txt"
    refute_file_matches "a/*.txt", "a/x/y.txt"
    refute_file_matches "a/*.txt", "a/x/y/z"

    assert_file_matches "a*.txt", "a.txt"
    refute_file_matches "a*.txt", "a/b.txt"
    refute_file_matches "a*.txt", "a/x/y.txt"
    refute_file_matches "a*.txt", "a/x/y/z"

    assert_file_matches "*.txt", "a.txt"
    refute_file_matches "*.txt", "a/b.txt"
    refute_file_matches "*.txt", "a/x/y.txt"
    refute_file_matches "*.txt", "a/x/y/z"

    refute_file_matches "a*", "a/b"
    refute_file_matches "a/**/b", "a/a/bb"
    refute_file_matches "a/**/b", "a/bb"

    refute_file_matches "*/**", "foo"
    refute_file_matches "**/", "foo/bar"
    refute_file_matches "**/*/", "foo/bar"
    refute_file_matches "*/*/", "foo/bar"

    assert_file_matches "**/..", "/home/foo/.."
    assert_file_matches "**/a", "a"
    assert_file_matches "**", "a/a"
    assert_file_matches "a/**", "a/a"
    assert_file_matches "a/**", "a/"
    # assert_file_matches "a/**", "a"
    refute_file_matches "**/", "a/a"
    # assert_file_matches "**/a/**", "a"
    # assert_file_matches "a/**", "a"
    refute_file_matches "**/", "a/a"
    assert_file_matches "*/**/a", "a/a"
    # assert_file_matches "a/**", "a"
    assert_file_matches "*/**", "foo/"
    assert_file_matches "**/*", "foo/bar"
    assert_file_matches "*/*", "foo/bar"
    assert_file_matches "*/**", "foo/bar"
    assert_file_matches "**/", "foo/bar/"
    # assert_file_matches "**/*", "foo/bar/"
    assert_file_matches "**/*/", "foo/bar/"
    assert_file_matches "*/**", "foo/bar/"
    assert_file_matches "*/*/", "foo/bar/"

    refute_file_matches "*/foo", "bar/baz/foo"
    refute_file_matches "**/bar/*", "deep/foo/bar"
    refute_file_matches "*/bar/**", "deep/foo/bar/baz/x"
    refute_file_matches "/*", "ef"
    refute_file_matches "foo?bar", "foo/bar"
    refute_file_matches "**/bar*", "foo/bar/baz"
    # refute_file_matches "**/bar**", "foo/bar/baz"
    refute_file_matches "foo**bar", "foo/baz/bar"
    refute_file_matches "foo*bar", "foo/baz/bar"
    # assert_file_matches "foo/**", "foo"
    assert_file_matches "/*", "/ab"
    assert_file_matches "/*", "/cd"
    assert_file_matches "/*", "/ef"
    assert_file_matches "a/**/j/**/z/*.md", "a/b/j/c/z/x.md"
    assert_file_matches "a/**/j/**/z/*.md", "a/j/z/x.md"

    assert_file_matches "**/foo", "bar/baz/foo"
    assert_file_matches "**/bar/*", "deep/foo/bar/baz"
    assert_file_matches "**/bar/**", "deep/foo/bar/baz/"
    assert_file_matches "**/bar/*/*", "deep/foo/bar/baz/x"
    assert_file_matches "foo/**/**/bar", "foo/b/a/z/bar"
    assert_file_matches "foo/**/bar", "foo/b/a/z/bar"
    assert_file_matches "foo/**/**/bar", "foo/bar"
    assert_file_matches "foo/**/bar", "foo/bar"
    assert_file_matches "*/bar/**", "foo/bar/baz/x"
    assert_file_matches "foo/**/**/bar", "foo/baz/bar"
    assert_file_matches "foo/**/bar", "foo/baz/bar"
    assert_file_matches "**/foo", "XXX/foo"
  end

  it "globstars" do
    assert_file_matches "**/*.js", "a/b/c/d.js"
    assert_file_matches "**/*.js", "a/b/c.js"
    assert_file_matches "**/*.js", "a/b.js"
    assert_file_matches "a/b/**/*.js", "a/b/c/d/e/f.js"
    assert_file_matches "a/b/**/*.js", "a/b/c/d/e.js"
    assert_file_matches "a/b/c/**/*.js", "a/b/c/d.js"
    assert_file_matches "a/b/**/*.js", "a/b/c/d.js"
    assert_file_matches "a/b/**/*.js", "a/b/d.js"
    refute_file_matches "a/b/**/*.js", "a/d.js"
    refute_file_matches "a/b/**/*.js", "d.js"

    refute_file_matches "**c", "a/b/c"
    refute_file_matches "a/**c", "a/b/c"
    refute_file_matches "a/**z", "a/b/c"
    refute_file_matches "a/**b**/c", "a/b/c/b/c"
    refute_file_matches "a/b/c**/*.js", "a/b/c/d/e.js"
    assert_file_matches "a/**/b/**/c", "a/b/c/b/c"
    assert_file_matches "a/**b**/c", "a/aba/c"
    assert_file_matches "a/**b**/c", "a/b/c"
    assert_file_matches "a/b/c**/*.js", "a/b/c/d.js"

    refute_file_matches "a/**/*", "a"
    refute_file_matches "a/**/**/*", "a"
    refute_file_matches "a/**/**/**/*", "a"
    refute_file_matches "**/a", "a/"
    assert_file_matches "a/**/*", "a/"
    assert_file_matches "a/**/**/*", "a/"
    assert_file_matches "a/**/**/**/*", "a/"
    refute_file_matches "**/a", "a/b"
    refute_file_matches "a/**/j/**/z/*.md", "a/b/c/j/e/z/c.txt"
    refute_file_matches "a/**/b", "a/bb"
    refute_file_matches "**/a", "a/c"
    refute_file_matches "**/a", "a/b"
    refute_file_matches "**/a", "a/x/y"
    refute_file_matches "**/a", "a/b/c/d"
    assert_file_matches "**", "a"
    assert_file_matches "**/a", "a"
    # assert_file_matches "a/**", "a"
    assert_file_matches "**", "a/"
    assert_file_matches "**/a/**", "a/"
    assert_file_matches "a/**", "a/"
    assert_file_matches "a/**/**", "a/"
    assert_file_matches "**/a", "a/a"
    assert_file_matches "**", "a/b"
    assert_file_matches "*/*", "a/b"
    assert_file_matches "a/**", "a/b"
    assert_file_matches "a/**/*", "a/b"
    assert_file_matches "a/**/**/*", "a/b"
    assert_file_matches "a/**/**/**/*", "a/b"
    assert_file_matches "a/**/b", "a/b"
    assert_file_matches "**", "a/b/c"
    assert_file_matches "**/*", "a/b/c"
    assert_file_matches "**/**", "a/b/c"
    assert_file_matches "*/**", "a/b/c"
    assert_file_matches "a/**", "a/b/c"
    assert_file_matches "a/**/*", "a/b/c"
    assert_file_matches "a/**/**/*", "a/b/c"
    assert_file_matches "a/**/**/**/*", "a/b/c"
    assert_file_matches "**", "a/b/c/d"
    assert_file_matches "a/**", "a/b/c/d"
    assert_file_matches "a/**/*", "a/b/c/d"
    assert_file_matches "a/**/**/*", "a/b/c/d"
    assert_file_matches "a/**/**/**/*", "a/b/c/d"
    assert_file_matches "a/b/**/c/**/*.*", "a/b/c/d.e"
    assert_file_matches "a/**/f/*.md", "a/b/c/d/e/f/g.md"
    assert_file_matches "a/**/f/**/k/*.md", "a/b/c/d/e/f/g/h/i/j/k/l.md"
    assert_file_matches "a/b/c/*.md", "a/b/c/def.md"
    assert_file_matches "a/*/c/*.md", "a/bb.bb/c/ddd.md"
    assert_file_matches "a/**/f/*.md", "a/bb.bb/cc/d.d/ee/f/ggg.md"
    assert_file_matches "a/**/f/*.md", "a/bb.bb/cc/dd/ee/f/ggg.md"
    assert_file_matches "a/*/c/*.md", "a/bb/c/ddd.md"
    assert_file_matches "a/*/c/*.md", "a/bbbb/c/ddd.md"

    assert_file_matches "foo/bar/**/one/**/*.*", "foo/bar/baz/one/image.png"
    assert_file_matches "foo/bar/**/one/**/*.*", "foo/bar/baz/one/two/image.png"
    assert_file_matches "foo/bar/**/one/**/*.*", "foo/bar/baz/one/two/three/image.png"
    refute_file_matches "a/b/**/f", "a/b/c/d/"
    # assert_file_matches "a/**", "a"
    assert_file_matches "**", "a"
    # assert_file_matches "a{,/**}", "a"
    assert_file_matches "**", "a/"
    assert_file_matches "a/**", "a/"
    assert_file_matches "**", "a/b/c/d"
    assert_file_matches "**", "a/b/c/d/"
    assert_file_matches "**/**", "a/b/c/d/"
    assert_file_matches "**/b/**", "a/b/c/d/"
    assert_file_matches "a/b/**", "a/b/c/d/"
    assert_file_matches "a/b/**/", "a/b/c/d/"
    assert_file_matches "a/b/**/c/**/", "a/b/c/d/"
    assert_file_matches "a/b/**/c/**/d/", "a/b/c/d/"
    assert_file_matches "a/b/**/**/*.*", "a/b/c/d/e.f"
    assert_file_matches "a/b/**/*.*", "a/b/c/d/e.f"
    assert_file_matches "a/b/**/c/**/d/*.*", "a/b/c/d/e.f"
    assert_file_matches "a/b/**/d/**/*.*", "a/b/c/d/e.f"
    assert_file_matches "a/b/**/d/**/*.*", "a/b/c/d/g/e.f"
    assert_file_matches "a/b/**/d/**/*.*", "a/b/c/d/g/g/e.f"
    assert_file_matches "a/b-*/**/z.js", "a/b-c/z.js"
    assert_file_matches "a/b-*/**/z.js", "a/b-c/d/e/z.js"

    assert_file_matches "*/*", "a/b"
    assert_file_matches "a/b/c/*.md", "a/b/c/xyz.md"
    assert_file_matches "a/*/c/*.md", "a/bb.bb/c/xyz.md"
    assert_file_matches "a/*/c/*.md", "a/bb/c/xyz.md"
    assert_file_matches "a/*/c/*.md", "a/bbbb/c/xyz.md"

    assert_file_matches "**/*", "a/b/c"
    assert_file_matches "**/**", "a/b/c"
    assert_file_matches "*/**", "a/b/c"
    assert_file_matches "a/**/j/**/z/*.md", "a/b/c/d/e/j/n/p/o/z/c.md"
    assert_file_matches "a/**/z/*.md", "a/b/c/d/e/z/c.md"
    assert_file_matches "a/**/c/*.md", "a/bb.bb/aa/b.b/aa/c/xyz.md"
    assert_file_matches "a/**/c/*.md", "a/bb.bb/aa/bb/aa/c/xyz.md"
    refute_file_matches "a/**/j/**/z/*.md", "a/b/c/j/e/z/c.txt"
    refute_file_matches "a/b/**/c{d,e}/**/xyz.md", "a/b/c/xyz.md"
    refute_file_matches "a/b/**/c{d,e}/**/xyz.md", "a/b/d/xyz.md"
    refute_file_matches "a/**/", "a/b"
    # refute_file_matches "**/*", "a/b/.js/c.txt"
    refute_file_matches "a/**/", "a/b/c/d"
    refute_file_matches "a/**/", "a/bb"
    refute_file_matches "a/**/", "a/cb"
    assert_file_matches "/**", "/a/b"
    assert_file_matches "**/*", "a.b"
    assert_file_matches "**/*", "a.js"
    assert_file_matches "**/*.js", "a.js"
    # assert_file_matches "a/**/", "a/"
    assert_file_matches "**/*.js", "a/a.js"
    assert_file_matches "**/*.js", "a/a/b.js"
    assert_file_matches "a/**/b", "a/b"
    assert_file_matches "a/**b", "a/b"
    assert_file_matches "**/*.md", "a/b.md"
    assert_file_matches "**/*", "a/b/c.js"
    assert_file_matches "**/*", "a/b/c.txt"
    assert_file_matches "a/**/", "a/b/c/d/"
    assert_file_matches "**/*", "a/b/c/d/a.js"
    assert_file_matches "a/b/**/*.js", "a/b/c/z.js"
    assert_file_matches "a/b/**/*.js", "a/b/z.js"
    assert_file_matches "**/*", "ab"
    assert_file_matches "**/*", "ab/c"
    assert_file_matches "**/*", "ab/c/d"
    assert_file_matches "**/*", "abc.js"

    refute_file_matches "**/", "a"
    refute_file_matches "**/a/*", "a"
    refute_file_matches "**/a/*/*", "a"
    refute_file_matches "*/a/**", "a"
    refute_file_matches "a/**/*", "a"
    refute_file_matches "a/**/**/*", "a"
    refute_file_matches "**/", "a/b"
    refute_file_matches "**/b/*", "a/b"
    refute_file_matches "**/b/*/*", "a/b"
    refute_file_matches "b/**", "a/b"
    refute_file_matches "**/", "a/b/c"
    refute_file_matches "**/**/b", "a/b/c"
    refute_file_matches "**/b", "a/b/c"
    refute_file_matches "**/b/*/*", "a/b/c"
    refute_file_matches "b/**", "a/b/c"
    refute_file_matches "**/", "a/b/c/d"
    refute_file_matches "**/d/*", "a/b/c/d"
    refute_file_matches "b/**", "a/b/c/d"
    assert_file_matches "**", "a"
    assert_file_matches "**/**", "a"
    assert_file_matches "**/**/*", "a"
    assert_file_matches "**/**/a", "a"
    assert_file_matches "**/a", "a"
    # assert_file_matches "**/a/**", "a"
    # assert_file_matches "a/**", "a"
    assert_file_matches "**", "a/b"
    assert_file_matches "**/**", "a/b"
    assert_file_matches "**/**/*", "a/b"
    assert_file_matches "**/**/b", "a/b"
    assert_file_matches "**/b", "a/b"
    # assert_file_matches "**/b/**", "a/b"
    # assert_file_matches "*/b/**", "a/b"
    assert_file_matches "a/**", "a/b"
    assert_file_matches "a/**/*", "a/b"
    assert_file_matches "a/**/**/*", "a/b"
    assert_file_matches "**", "a/b/c"
    assert_file_matches "**/**", "a/b/c"
    assert_file_matches "**/**/*", "a/b/c"
    assert_file_matches "**/b/*", "a/b/c"
    assert_file_matches "**/b/**", "a/b/c"
    assert_file_matches "*/b/**", "a/b/c"
    assert_file_matches "a/**", "a/b/c"
    assert_file_matches "a/**/*", "a/b/c"
    assert_file_matches "a/**/**/*", "a/b/c"
    assert_file_matches "**", "a/b/c/d"
    assert_file_matches "**/**", "a/b/c/d"
    assert_file_matches "**/**/*", "a/b/c/d"
    assert_file_matches "**/**/d", "a/b/c/d"
    assert_file_matches "**/b/**", "a/b/c/d"
    assert_file_matches "**/b/*/*", "a/b/c/d"
    assert_file_matches "**/d", "a/b/c/d"
    assert_file_matches "*/b/**", "a/b/c/d"
    assert_file_matches "a/**", "a/b/c/d"
    assert_file_matches "a/**/*", "a/b/c/d"
    assert_file_matches "a/**/**/*", "a/b/c/d"

    assert_file_matches "**/**.txt.js", "/foo/bar.txt.js"
  end

  it "utf8" do
    assert_file_matches "フ*/**/*", "フォルダ/aaa.js"
    assert_file_matches "フォ*/**/*", "フォルダ/aaa.js"
    assert_file_matches "フォル*/**/*", "フォルダ/aaa.js"
    assert_file_matches "フ*ル*/**/*", "フォルダ/aaa.js"
    assert_file_matches "フォルダ/**/*", "フォルダ/aaa.js"
  end

  pending "negation" do
    refute_file_matches "!*", "abc"
    refute_file_matches "!abc", "abc"
    refute_file_matches "*!.md", "bar.md"
    refute_file_matches "foo!.md", "bar.md"
    refute_file_matches "\\!*!*.md", "foo!.md"
    refute_file_matches "\\!*!*.md", "foo!bar.md"
    assert_file_matches "*!*.md", "!foo!.md"
    assert_file_matches "\\!*!*.md", "!foo!.md"
    assert_file_matches "!*foo", "abc"
    assert_file_matches "!foo*", "abc"
    assert_file_matches "!xyz", "abc"
    assert_file_matches "*!*.*", "ba!r.js"
    assert_file_matches "*.md", "bar.md"
    assert_file_matches "*!*.*", "foo!.md"
    assert_file_matches "*!*.md", "foo!.md"
    assert_file_matches "*!.md", "foo!.md"
    assert_file_matches "*.md", "foo!.md"
    assert_file_matches "foo!.md", "foo!.md"
    assert_file_matches "*!*.md", "foo!bar.md"
    assert_file_matches "*b*.md", "foobar.md"

    refute_file_matches "a!!b", "a"
    refute_file_matches "a!!b", "aa"
    refute_file_matches "a!!b", "a/b"
    refute_file_matches "a!!b", "a!b"
    assert_file_matches "a!!b", "a!!b"
    refute_file_matches "a!!b", "a/!!/b"

    refute_file_matches "!a/b", "a/b"
    assert_file_matches "!a/b", "a"
    assert_file_matches "!a/b", "a.b"
    assert_file_matches "!a/b", "a/a"
    assert_file_matches "!a/b", "a/c"
    assert_file_matches "!a/b", "b/a"
    assert_file_matches "!a/b", "b/b"
    assert_file_matches "!a/b", "b/c"

    refute_file_matches "!abc", "abc"
    assert_file_matches "!!abc", "abc"
    refute_file_matches "!!!abc", "abc"
    assert_file_matches "!!!!abc", "abc"
    refute_file_matches "!!!!!abc", "abc"
    assert_file_matches "!!!!!!abc", "abc"
    refute_file_matches "!!!!!!!abc", "abc"
    assert_file_matches "!!!!!!!!abc", "abc"

    # refute_file_matches "!(*/*)", "a/a"
    # refute_file_matches "!(*/*)", "a/b"
    # refute_file_matches "!(*/*)", "a/c"
    # refute_file_matches "!(*/*)", "b/a"
    # refute_file_matches "!(*/*)", "b/b"
    # refute_file_matches "!(*/*)", "b/c"
    # refute_file_matches "!(*/b)", "a/b"
    # refute_file_matches "!(*/b)", "b/b"
    # refute_file_matches "!(a/b)", "a/b"
    refute_file_matches "!*", "a"
    refute_file_matches "!*", "a.b"
    refute_file_matches "!*/*", "a/a"
    refute_file_matches "!*/*", "a/b"
    refute_file_matches "!*/*", "a/c"
    refute_file_matches "!*/*", "b/a"
    refute_file_matches "!*/*", "b/b"
    refute_file_matches "!*/*", "b/c"
    refute_file_matches "!*/b", "a/b"
    refute_file_matches "!*/b", "b/b"
    refute_file_matches "!*/c", "a/c"
    refute_file_matches "!*/c", "b/c"
    refute_file_matches "!*a*", "bar"
    refute_file_matches "!*a*", "fab"
    # refute_file_matches "!a/(*)", "a/a"
    # refute_file_matches "!a/(*)", "a/b"
    # refute_file_matches "!a/(*)", "a/c"
    # refute_file_matches "!a/(b)", "a/b"
    refute_file_matches "!a/*", "a/a"
    refute_file_matches "!a/*", "a/b"
    refute_file_matches "!a/*", "a/c"
    refute_file_matches "!f*b", "fab"
    # assert_file_matches "!(*/*)", "a"
    # assert_file_matches "!(*/*)", "a.b"
    # assert_file_matches "!(*/b)", "a"
    # assert_file_matches "!(*/b)", "a.b"
    # assert_file_matches "!(*/b)", "a/a"
    # assert_file_matches "!(*/b)", "a/c"
    # assert_file_matches "!(*/b)", "b/a"
    # assert_file_matches "!(*/b)", "b/c"
    # assert_file_matches "!(a/b)", "a"
    # assert_file_matches "!(a/b)", "a.b"
    # assert_file_matches "!(a/b)", "a/a"
    # assert_file_matches "!(a/b)", "a/c"
    # assert_file_matches "!(a/b)", "b/a"
    # assert_file_matches "!(a/b)", "b/b"
    # assert_file_matches "!(a/b)", "b/c"
    assert_file_matches "!*", "a/a"
    assert_file_matches "!*", "a/b"
    assert_file_matches "!*", "a/c"
    assert_file_matches "!*", "b/a"
    assert_file_matches "!*", "b/b"
    assert_file_matches "!*", "b/c"
    assert_file_matches "!*/*", "a"
    assert_file_matches "!*/*", "a.b"
    assert_file_matches "!*/b", "a"
    assert_file_matches "!*/b", "a.b"
    assert_file_matches "!*/b", "a/a"
    assert_file_matches "!*/b", "a/c"
    assert_file_matches "!*/b", "b/a"
    assert_file_matches "!*/b", "b/c"
    assert_file_matches "!*/c", "a"
    assert_file_matches "!*/c", "a.b"
    assert_file_matches "!*/c", "a/a"
    assert_file_matches "!*/c", "a/b"
    assert_file_matches "!*/c", "b/a"
    assert_file_matches "!*/c", "b/b"
    assert_file_matches "!*a*", "foo"
    # assert_file_matches "!a/(*)", "a"
    # assert_file_matches "!a/(*)", "a.b"
    # assert_file_matches "!a/(*)", "b/a"
    # assert_file_matches "!a/(*)", "b/b"
    # assert_file_matches "!a/(*)", "b/c"
    # assert_file_matches "!a/(b)", "a"
    # assert_file_matches "!a/(b)", "a.b"
    # assert_file_matches "!a/(b)", "a/a"
    # assert_file_matches "!a/(b)", "a/c"
    # assert_file_matches "!a/(b)", "b/a"
    # assert_file_matches "!a/(b)", "b/b"
    # assert_file_matches "!a/(b)", "b/c"
    assert_file_matches "!a/*", "a"
    assert_file_matches "!a/*", "a.b"
    assert_file_matches "!a/*", "b/a"
    assert_file_matches "!a/*", "b/b"
    assert_file_matches "!a/*", "b/c"
    assert_file_matches "!f*b", "bar"
    assert_file_matches "!f*b", "foo"

    refute_file_matches "!.md", ".md"
    assert_file_matches "!**/*.md", "a.js"
    # refute_file_matches "!**/*.md", "b.md"
    assert_file_matches "!**/*.md", "c.txt"
    assert_file_matches "!*.md", "a.js"
    refute_file_matches "!*.md", "b.md"
    assert_file_matches "!*.md", "c.txt"
    refute_file_matches "!*.md", "abc.md"
    assert_file_matches "!*.md", "abc.txt"
    refute_file_matches "!*.md", "foo.md"
    assert_file_matches "!.md", "foo.md"

    assert_file_matches "!*.md", "a.js"
    assert_file_matches "!*.md", "b.txt"
    refute_file_matches "!*.md", "c.md"
    refute_file_matches "!a/*/a.js", "a/a/a.js"
    refute_file_matches "!a/*/a.js", "a/b/a.js"
    refute_file_matches "!a/*/a.js", "a/c/a.js"
    refute_file_matches "!a/*/*/a.js", "a/a/a/a.js"
    assert_file_matches "!a/*/*/a.js", "b/a/b/a.js"
    assert_file_matches "!a/*/*/a.js", "c/a/c/a.js"
    refute_file_matches "!a/a*.txt", "a/a.txt"
    assert_file_matches "!a/a*.txt", "a/b.txt"
    assert_file_matches "!a/a*.txt", "a/c.txt"
    refute_file_matches "!a.a*.txt", "a.a.txt"
    assert_file_matches "!a.a*.txt", "a.b.txt"
    assert_file_matches "!a.a*.txt", "a.c.txt"
    refute_file_matches "!a/*.txt", "a/a.txt"
    refute_file_matches "!a/*.txt", "a/b.txt"
    refute_file_matches "!a/*.txt", "a/c.txt"

    assert_file_matches "!*.md", "a.js"
    assert_file_matches "!*.md", "b.txt"
    refute_file_matches "!*.md", "c.md"
    # refute_file_matches "!**/a.js", "a/a/a.js"
    # refute_file_matches "!**/a.js", "a/b/a.js"
    # refute_file_matches "!**/a.js", "a/c/a.js"
    assert_file_matches "!**/a.js", "a/a/b.js"
    refute_file_matches "!a/**/a.js", "a/a/a/a.js"
    assert_file_matches "!a/**/a.js", "b/a/b/a.js"
    assert_file_matches "!a/**/a.js", "c/a/c/a.js"
    assert_file_matches "!**/*.md", "a/b.js"
    assert_file_matches "!**/*.md", "a.js"
    refute_file_matches "!**/*.md", "a/b.md"
    # refute_file_matches "!**/*.md", "a.md"
    refute_file_matches "**/*.md", "a/b.js"
    refute_file_matches "**/*.md", "a.js"
    assert_file_matches "**/*.md", "a/b.md"
    assert_file_matches "**/*.md", "a.md"
    assert_file_matches "!**/*.md", "a/b.js"
    assert_file_matches "!**/*.md", "a.js"
    refute_file_matches "!**/*.md", "a/b.md"
    # refute_file_matches "!**/*.md", "a.md"
    assert_file_matches "!*.md", "a/b.js"
    assert_file_matches "!*.md", "a.js"
    assert_file_matches "!*.md", "a/b.md"
    refute_file_matches "!*.md", "a.md"
    assert_file_matches "!**/*.md", "a.js"
    # refute_file_matches "!**/*.md", "b.md"
    assert_file_matches "!**/*.md", "c.txt"
  end

  it "question_mark" do
    assert_file_matches "?", "a"
    refute_file_matches "?", "aa"
    refute_file_matches "?", "ab"
    refute_file_matches "?", "aaa"
    refute_file_matches "?", "abcdefg"

    refute_file_matches "??", "a"
    assert_file_matches "??", "aa"
    assert_file_matches "??", "ab"
    refute_file_matches "??", "aaa"
    refute_file_matches "??", "abcdefg"

    refute_file_matches "???", "a"
    refute_file_matches "???", "aa"
    refute_file_matches "???", "ab"
    assert_file_matches "???", "aaa"
    refute_file_matches "???", "abcdefg"

    refute_file_matches "a?c", "aaa"
    assert_file_matches "a?c", "aac"
    assert_file_matches "a?c", "abc"
    refute_file_matches "ab?", "a"
    refute_file_matches "ab?", "aa"
    refute_file_matches "ab?", "ab"
    refute_file_matches "ab?", "ac"
    refute_file_matches "ab?", "abcd"
    refute_file_matches "ab?", "abbb"
    assert_file_matches "a?b", "acb"

    refute_file_matches "a/?/c/?/e.md", "a/bb/c/dd/e.md"
    assert_file_matches "a/??/c/??/e.md", "a/bb/c/dd/e.md"
    refute_file_matches "a/??/c.md", "a/bbb/c.md"
    assert_file_matches "a/?/c.md", "a/b/c.md"
    assert_file_matches "a/?/c/?/e.md", "a/b/c/d/e.md"
    refute_file_matches "a/?/c/???/e.md", "a/b/c/d/e.md"
    assert_file_matches "a/?/c/???/e.md", "a/b/c/zzz/e.md"
    refute_file_matches "a/?/c.md", "a/bb/c.md"
    assert_file_matches "a/??/c.md", "a/bb/c.md"
    assert_file_matches "a/???/c.md", "a/bbb/c.md"
    assert_file_matches "a/????/c.md", "a/bbbb/c.md"
  end

  it "braces" do
    assert_file_matches "{a,b,c}", "a"
    assert_file_matches "{a,b,c}", "b"
    assert_file_matches "{a,b,c}", "c"
    refute_file_matches "{a,b,c}", "aa"
    refute_file_matches "{a,b,c}", "bb"
    refute_file_matches "{a,b,c}", "cc"

    assert_file_matches "a/{a,b}", "a/a"
    assert_file_matches "a/{a,b}", "a/b"
    refute_file_matches "a/{a,b}", "a/c"
    refute_file_matches "a/{a,b}", "b/b"
    refute_file_matches "a/{a,b,c}", "b/b"
    assert_file_matches "a/{a,b,c}", "a/c"
    assert_file_matches "a{b,bc}.txt", "abc.txt"

    assert_file_matches "foo[{a,b}]baz", "foo{baz"

    refute_file_matches "a{,b}.txt", "abc.txt"
    refute_file_matches "a{a,b,}.txt", "abc.txt"
    refute_file_matches "a{b,}.txt", "abc.txt"
    assert_file_matches "a{,b}.txt", "a.txt"
    assert_file_matches "a{b,}.txt", "a.txt"
    assert_file_matches "a{a,b,}.txt", "aa.txt"
    assert_file_matches "a{,b}.txt", "ab.txt"
    assert_file_matches "a{b,}.txt", "ab.txt"

    # assert_file_matches "{a/,}a/**", "a"
    assert_file_matches "a{a,b/}*.txt", "aa.txt"
    assert_file_matches "a{a,b/}*.txt", "ab/.txt"
    assert_file_matches "a{a,b/}*.txt", "ab/a.txt"
    # assert_file_matches "{a/,}a/**", "a/"
    assert_file_matches "{a/,}a/**", "a/a/"
    # assert_file_matches "{a/,}a/**", "a/a"
    assert_file_matches "{a/,}a/**", "a/a/a"
    assert_file_matches "{a/,}a/**", "a/a/"
    assert_file_matches "{a/,}a/**", "a/a/a/"
    assert_file_matches "{a/,}b/**", "a/b/a/"
    assert_file_matches "{a/,}b/**", "b/a/"
    assert_file_matches "a{,/}*.txt", "a.txt"
    assert_file_matches "a{,/}*.txt", "ab.txt"
    assert_file_matches "a{,/}*.txt", "a/b.txt"
    assert_file_matches "a{,/}*.txt", "a/ab.txt"

    assert_file_matches "a{,.*{foo,db},\\(bar\\)}.txt", "a.txt"
    refute_file_matches "a{,.*{foo,db},\\(bar\\)}.txt", "adb.txt"
    assert_file_matches "a{,.*{foo,db},\\(bar\\)}.txt", "a.db.txt"

    assert_file_matches "a{,*.{foo,db},\\(bar\\)}.txt", "a.txt"
    refute_file_matches "a{,*.{foo,db},\\(bar\\)}.txt", "adb.txt"
    assert_file_matches "a{,*.{foo,db},\\(bar\\)}.txt", "a.db.txt"

    # assert_file_matches "a{,.*{foo,db},\\(bar\\)}", "a"
    refute_file_matches "a{,.*{foo,db},\\(bar\\)}", "adb"
    assert_file_matches "a{,.*{foo,db},\\(bar\\)}", "a.db"

    # assert_file_matches "a{,*.{foo,db},\\(bar\\)}", "a"
    refute_file_matches "a{,*.{foo,db},\\(bar\\)}", "adb"
    assert_file_matches "a{,*.{foo,db},\\(bar\\)}", "a.db"

    refute_file_matches "{,.*{foo,db},\\(bar\\)}", "a"
    refute_file_matches "{,.*{foo,db},\\(bar\\)}", "adb"
    refute_file_matches "{,.*{foo,db},\\(bar\\)}", "a.db"
    assert_file_matches "{,.*{foo,db},\\(bar\\)}", ".db"

    refute_file_matches "{,*.{foo,db},\\(bar\\)}", "a"
    assert_file_matches "{*,*.{foo,db},\\(bar\\)}", "a"
    refute_file_matches "{,*.{foo,db},\\(bar\\)}", "adb"
    assert_file_matches "{,*.{foo,db},\\(bar\\)}", "a.db"

    refute_file_matches "a/b/**/c{d,e}/**/xyz.md", "a/b/c/xyz.md"
    refute_file_matches "a/b/**/c{d,e}/**/xyz.md", "a/b/d/xyz.md"
    assert_file_matches "a/b/**/c{d,e}/**/xyz.md", "a/b/cd/xyz.md"
    assert_file_matches "a/b/**/{c,d,e}/**/xyz.md", "a/b/c/xyz.md"
    assert_file_matches "a/b/**/{c,d,e}/**/xyz.md", "a/b/d/xyz.md"
    assert_file_matches "a/b/**/{c,d,e}/**/xyz.md", "a/b/e/xyz.md"

    assert_file_matches "*{a,b}*", "xax"
    assert_file_matches "*{a,b}*", "xxax"
    assert_file_matches "*{a,b}*", "xbx"

    assert_file_matches "*{*a,b}", "xba"
    assert_file_matches "*{*a,b}", "xb"

    refute_file_matches "*??", "a"
    refute_file_matches "*???", "aa"
    assert_file_matches "*???", "aaa"
    refute_file_matches "*****??", "a"
    refute_file_matches "*****???", "aa"
    assert_file_matches "*****???", "aaa"

    refute_file_matches "a*?c", "aaa"
    assert_file_matches "a*?c", "aac"
    assert_file_matches "a*?c", "abc"

    assert_file_matches "a**?c", "abc"
    refute_file_matches "a**?c", "abb"
    assert_file_matches "a**?c", "acc"
    assert_file_matches "a*****?c", "abc"

    assert_file_matches "*****?", "a"
    assert_file_matches "*****?", "aa"
    assert_file_matches "*****?", "abc"
    assert_file_matches "*****?", "zzz"
    assert_file_matches "*****?", "bbb"
    assert_file_matches "*****?", "aaaa"

    refute_file_matches "*****??", "a"
    assert_file_matches "*****??", "aa"
    assert_file_matches "*****??", "abc"
    assert_file_matches "*****??", "zzz"
    assert_file_matches "*****??", "bbb"
    assert_file_matches "*****??", "aaaa"

    refute_file_matches "?*****??", "a"
    refute_file_matches "?*****??", "aa"
    assert_file_matches "?*****??", "abc"
    assert_file_matches "?*****??", "zzz"
    assert_file_matches "?*****??", "bbb"
    assert_file_matches "?*****??", "aaaa"

    assert_file_matches "?*****?c", "abc"
    refute_file_matches "?*****?c", "abb"
    refute_file_matches "?*****?c", "zzz"

    assert_file_matches "?***?****c", "abc"
    refute_file_matches "?***?****c", "bbb"
    refute_file_matches "?***?****c", "zzz"

    assert_file_matches "?***?****?", "abc"
    assert_file_matches "?***?****?", "bbb"
    assert_file_matches "?***?****?", "zzz"

    assert_file_matches "?***?****", "abc"
    assert_file_matches "*******c", "abc"
    assert_file_matches "*******?", "abc"
    assert_file_matches "a*cd**?**??k", "abcdecdhjk"
    assert_file_matches "a**?**cd**?**??k", "abcdecdhjk"
    assert_file_matches "a**?**cd**?**??k***", "abcdecdhjk"
    assert_file_matches "a**?**cd**?**??***k", "abcdecdhjk"
    assert_file_matches "a**?**cd**?**??***k**", "abcdecdhjk"
    assert_file_matches "a****c**?**??*****", "abcdecdhjk"

    refute_file_matches "a/?/c/?/*/e.md", "a/b/c/d/e.md"
    assert_file_matches "a/?/c/?/*/e.md", "a/b/c/d/e/e.md"
    assert_file_matches "a/?/c/?/*/e.md", "a/b/c/d/efghijk/e.md"
    assert_file_matches "a/?/**/e.md", "a/b/c/d/efghijk/e.md"
    refute_file_matches "a/?/e.md", "a/bb/e.md"
    assert_file_matches "a/??/e.md", "a/bb/e.md"
    refute_file_matches "a/?/**/e.md", "a/bb/e.md"
    assert_file_matches "a/?/**/e.md", "a/b/ccc/e.md"
    assert_file_matches "a/*/?/**/e.md", "a/b/c/d/efghijk/e.md"
    assert_file_matches "a/*/?/**/e.md", "a/b/c/d/efgh.ijk/e.md"
    assert_file_matches "a/*/?/**/e.md", "a/b.bb/c/d/efgh.ijk/e.md"
    assert_file_matches "a/*/?/**/e.md", "a/bbb/c/d/efgh.ijk/e.md"

    assert_file_matches "a/*/ab??.md", "a/bbb/abcd.md"
    assert_file_matches "a/bbb/ab??.md", "a/bbb/abcd.md"
    assert_file_matches "a/bbb/ab???md", "a/bbb/abcd.md"

    assert_file_matches "{a,b}/c/{d,e}/**/*.ts", "a/c/d/one/two/three.test.ts"
    assert_file_matches "{a,{d,e}b}/c", "a/c"
    assert_file_matches "{**/a,**/b}", "b"
  end

  it "not_paired_braces" do
    refute_file_matches "{a,}}", "a"
    assert_file_matches "{a,}}", "a}"
  end
end
