require_relative '../../spec_helper' describe "File.join" do # see [ruby-core:46804] for the 4 following rules it "changes only boundaries separators" do File.join("file/\\/usr/", "/bin").should == "file/\\/usr/bin" File.join("file://usr", "bin").should == "file://usr/bin" end it "respects the given separator if only one part has a boundary separator" do File.join("usr/", "bin").should == "usr/bin" File.join("usr", "/bin").should == "usr/bin" File.join("usr//", "bin").should == "usr//bin" File.join("usr", "//bin").should == "usr//bin" end it "joins parts using File::SEPARATOR if there are no boundary separators" do File.join("usr", "bin").should == "usr/bin" end it "prefers the separator of the right part if both parts have separators" do File.join("usr/", "//bin").should == "usr//bin" File.join("usr//", "/bin").should == "usr/bin" end platform_is :windows do it "respects given separator if only one part has a boundary separator" do File.join("C:\\", 'windows').should == "C:\\windows" File.join("C:", "\\windows").should == "C:\\windows" File.join("\\\\", "usr").should == "\\\\usr" end it "prefers the separator of the right part if both parts have separators" do File.join("C:/", "\\windows").should == "C:\\windows" File.join("C:\\", "/windows").should == "C:/windows" end end platform_is_not :windows do it "does not treat \\ as a separator on non-Windows" do File.join("usr\\", 'bin').should == "usr\\/bin" File.join("usr", "\\bin").should == "usr/\\bin" File.join("usr/", "\\bin").should == "usr/\\bin" File.join("usr\\", "/bin").should == "usr\\/bin" end end it "returns an empty string when given no arguments" do File.join.should == "" end it "returns a duplicate string when given a single argument" do str = "usr" File.join(str).should == str File.join(str).should_not equal(str) end it "supports any number of arguments" do File.join("a", "b", "c", "d").should == "a/b/c/d" end it "flattens nested arrays" do File.join(["a", "b", "c"]).should == "a/b/c" File.join(["a", ["b", ["c"]]]).should == "a/b/c" end it "inserts the separator in between empty strings and arrays" do File.join("").should == "" File.join("", "").should == "/" File.join(["", ""]).should == "/" File.join("a", "").should == "a/" File.join("", "a").should == "/a" File.join([]).should == "" File.join([], []).should == "/" File.join([[], []]).should == "/" File.join("a", []).should == "a/" File.join([], "a").should == "/a" end it "handles leading parts edge cases" do File.join("/bin") .should == "/bin" File.join("", "bin") .should == "/bin" File.join("/", "bin") .should == "/bin" File.join("/", "/bin").should == "/bin" end it "handles trailing parts edge cases" do File.join("bin", "") .should == "bin/" File.join("bin/") .should == "bin/" File.join("bin/", "") .should == "bin/" File.join("bin", "/") .should == "bin/" File.join("bin/", "/").should == "bin/" end it "handles middle parts edge cases" do File.join("usr", "", "bin") .should == "usr/bin" File.join("usr/", "", "bin") .should == "usr/bin" File.join("usr", "", "/bin").should == "usr/bin" File.join("usr/", "", "/bin").should == "usr/bin" end # TODO: See MRI svn r23306. Add patchlevel when there is a release. it "raises an ArgumentError if passed a recursive array" do a = ["a"] a << a -> { File.join a }.should raise_error(ArgumentError) end it "raises a TypeError exception when args are nil" do -> { File.join nil }.should raise_error(TypeError) end it "calls #to_str" do -> { File.join(mock('x')) }.should raise_error(TypeError) bin = mock("bin") bin.should_receive(:to_str).exactly(:twice).and_return("bin") File.join(bin).should == "bin" File.join("usr", bin).should == "usr/bin" end it "doesn't mutate the object when calling #to_str" do usr = mock("usr") str = "usr" usr.should_receive(:to_str).and_return(str) File.join(usr, "bin").should == "usr/bin" str.should == "usr" end it "calls #to_path" do -> { File.join(mock('x')) }.should raise_error(TypeError) bin = mock("bin") bin.should_receive(:to_path).exactly(:twice).and_return("bin") File.join(bin).should == "bin" File.join("usr", bin).should == "usr/bin" end it "raises errors for null bytes" do -> { File.join("\x00x", "metadata.gz") }.should raise_error(ArgumentError) { |e| e.message.should == 'string contains null byte' } -> { File.join("metadata.gz", "\x00x") }.should raise_error(ArgumentError) { |e| e.message.should == 'string contains null byte' } end end