require File.expand_path(File.dirname(__FILE__) + '/spec_helper')

require 'hx/path'

describe Hx::Path::Pattern do
  it "should include Hx::Path::Selector" do
    Hx::Path::Pattern.should < Hx::Path::Selector
  end

  it "should parse pattern strings" do
    cases = [ { :pattern => "foo/**/bar",
                :prefix => "foo/",
                :suffix => "/bar" },
              { :pattern => "foo/*/bar",
                :prefix => "foo/",
                :suffix => "/bar" },
              { :pattern => "[blah",
                :prefix => "[blah",
                :suffix => "" },
              { :pattern => "hoge*",
                :prefix => "hoge",
                :suffix => "" },
              { :pattern => "*hoge",
                :prefix => "",
                :suffix => "hoge" } ]
    for test_case in cases
      pattern = Hx::Path.parse_pattern(test_case[:pattern])
      pattern.prefix.should == test_case[:prefix]
      pattern.suffix.should == test_case[:suffix]
    end
  end

  it "should accept or reject paths" do
    pattern = Hx::Path.parse_pattern("foo/bar")
    pattern.should accept("foo/bar")
    pattern.should_not accept("foo/baz")
  end

  it "should provide an equivalent regexp" do
    pattern = Hx::Path.parse_pattern("foo/bar")
    pattern.regexp.should_not be_nil
    pattern.regexp.match("foo/bar").should_not be_nil
    pattern.regexp.match("foo/bar/baz").should be_nil

    pattern = Hx::Path.parse_pattern("foo/*/baz")
    pattern.regexp.should_not be_nil
    pattern.regexp.match("foo/baz").should be_nil
    pattern.regexp.match("foo/bar/baz").should_not be_nil
  end
end

PATHFILTER_PREFIX_CASES = [
  { :patterns => ["foo/bar", "fudge/bear"],
    :prefix => "f",
    :suffix => "ar" },
  { :patterns => ["foo/*/bar", "fudge/*/bear"],
    :prefix => "f",
    :suffix => "ar" },
  { :patterns => ["foo/bar", "fudge/*/bear"],
    :prefix => "f",
    :suffix => "ar" },
  { :patterns => ["bar*", "*bear"],
    :prefix => "",
    :suffix => "" },
  { :patterns => ["foobarbaz", "foobar*barbaz"],
    :prefix => "foobar",
    :suffix => "baz" },
  { :patterns => ["foobarbaz*", "foobar*barbaz"],
    :prefix => "foobar",
    :suffix => "" },
  { :patterns => ["*foobarbaz", "foobar*barbaz"],
    :prefix => "",
    :suffix => "barbaz" }
]

describe "Hx::Path::Selector disjunctions" do
  it "should be possible" do
    filters = ["foo/bar", "abcdefg"].map { |p| Hx::Path.parse_pattern(p) }
    filter = filters.inject { |a, b| a | b }
    filter.should be_a_kind_of(Hx::Path::Selector)
  end

  it "should accept and reject the right paths" do
    filters = ["foo/bar", "abcdefg"].map { |p| Hx::Path.parse_pattern(p) }
    filter = filters.inject { |a, b| a | b }
    filter.should accept("foo/bar")
    filter.should accept("abcdefg")
    filter.should_not accept("hoge")
  end

  for test_case_outer in PATHFILTER_PREFIX_CASES
    Proc.new do |test_case|
      it "should produce optimal prefixes and suffixes" do
        filters = test_case[:patterns].map { |p| Hx::Path.parse_pattern(p) }
        filter = filters.inject { |a, b| a | b }
        filter.prefix.should == test_case[:prefix]
        filter.suffix.should == test_case[:suffix]
      end
    end.call(test_case_outer)
  end
end

describe "negated Hx::Path::Selectors" do
  before :each do
    @pattern = ~Hx::Path.parse_pattern("foo*bar")
  end

  it "should be possible" do
    @pattern.should be_a_kind_of(Hx::Path::Selector)
  end

  it "should reject what they match" do
    @pattern.should_not accept("foobar")
    @pattern.should accept("hoge")
  end

  it "should have empty prefix and suffix" do
    @pattern.prefix.should == ""
    @pattern.suffix.should == ""
  end
end

describe "Hx::Path::Selector conjunctions" do
  it "should be possible" do
    filters = ["foo*", "*bar"].map { |p| Hx::Path.parse_pattern(p) }
    filter = filters.inject { |a, b| a & b }
    filter.should be_a_kind_of(Hx::Path::Selector)
  end

  it "should accept only paths matching both filters" do
    filters = ["foo*", "*bar"].map { |p| Hx::Path.parse_pattern(p) }
    filter = filters.inject { |a, b| a & b }
    filter.should accept("foobar")
    filter.should accept("fooxbar")
    filter.should_not accept("lemur")
    filter.should_not accept("foobear")
    filter.should_not accept("rebar")
  end

  for test_case_outer in PATHFILTER_PREFIX_CASES
    Proc.new do |test_case|
      it "should produce optimal prefixes and suffixes" do
        filters = test_case[:patterns].map { |p| Hx::Path.parse_pattern(p) }
        filter = filters.inject { |a, b| a & b }
        filter.prefix.should == test_case[:prefix]
        filter.suffix.should == test_case[:suffix]
      end
    end.call(test_case_outer)
  end
end