# # Author:: AJ Christensen () # Author:: John Keiser () # Copyright:: Copyright 2008-2016, Chef Software Inc. # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require "ostruct" require "spec_helper" if Chef::Platform.windows? require "chef/win32/file" #probably need this in spec_helper end describe Chef::Resource::Link, :not_supported_on_win2k3 do let(:provider) do node = Chef::Node.new @events = Chef::EventDispatch::Dispatcher.new run_context = Chef::RunContext.new(node, {}, @events) Chef::Provider::Link.new(new_resource, run_context) end let(:new_resource) do result = Chef::Resource::Link.new("#{CHEF_SPEC_DATA}/fofile-link") result.to "#{CHEF_SPEC_DATA}/fofile" result end def canonicalize(path) Chef::Platform.windows? ? path.tr("/", '\\') : path end describe "when the target is a symlink" do before(:each) do lstat = double("stats", :ino => 5) allow(lstat).to receive(:uid).and_return(501) allow(lstat).to receive(:gid).and_return(501) allow(lstat).to receive(:mode).and_return(0777) allow(File).to receive(:lstat).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(lstat) allow(provider.file_class).to receive(:symlink?).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(true) allow(provider.file_class).to receive(:readlink).with("#{CHEF_SPEC_DATA}/fofile-link").and_return("#{CHEF_SPEC_DATA}/fofile") end describe "to a file that exists" do before do allow(File).to receive(:exist?).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(true) new_resource.owner 501 # only loaded in current_resource if present in new new_resource.group 501 provider.load_current_resource end it "should set the symlink target" do expect(provider.current_resource.target_file).to eq("#{CHEF_SPEC_DATA}/fofile-link") end it "should set the link type" do expect(provider.current_resource.link_type).to eq(:symbolic) end it "should update the source of the existing link with the links target" do expect(provider.current_resource.to).to eq(canonicalize("#{CHEF_SPEC_DATA}/fofile")) end it "should set the owner" do expect(provider.current_resource.owner).to eq(501) end it "should set the group" do expect(provider.current_resource.group).to eq(501) end # We test create in unit tests because there is no other way to ensure # it does no work. Other create and delete scenarios are covered in # the functional tests for links. context "when the desired state is identical" do let(:new_resource) do result = Chef::Resource::Link.new("#{CHEF_SPEC_DATA}/fofile-link") result.to "#{CHEF_SPEC_DATA}/fofile" result end it "create does no work" do expect(provider.access_controls).not_to receive(:set_all) provider.run_action(:create) end end end describe "to a file that doesn't exist" do before do allow(File).to receive(:exist?).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(false) allow(provider.file_class).to receive(:symlink?).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(true) allow(provider.file_class).to receive(:readlink).with("#{CHEF_SPEC_DATA}/fofile-link").and_return("#{CHEF_SPEC_DATA}/fofile") new_resource.owner "501" # only loaded in current_resource if present in new new_resource.group "501" provider.load_current_resource end it "should set the symlink target" do expect(provider.current_resource.target_file).to eq("#{CHEF_SPEC_DATA}/fofile-link") end it "should set the link type" do expect(provider.current_resource.link_type).to eq(:symbolic) end it "should update the source of the existing link to the link's target" do expect(provider.current_resource.to).to eq(canonicalize("#{CHEF_SPEC_DATA}/fofile")) end it "should not set the owner" do expect(provider.current_resource.owner).to be_nil end it "should not set the group" do expect(provider.current_resource.group).to be_nil end end end describe "when the target doesn't exist" do before do allow(File).to receive(:exists?).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(false) allow(provider.file_class).to receive(:symlink?).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(false) provider.load_current_resource end it "should set the symlink target" do expect(provider.current_resource.target_file).to eq("#{CHEF_SPEC_DATA}/fofile-link") end it "should update the source of the existing link to nil" do expect(provider.current_resource.to).to be_nil end it "should not set the owner" do expect(provider.current_resource.owner).to eq(nil) end it "should not set the group" do expect(provider.current_resource.group).to eq(nil) end end describe "when the target is a regular old file" do before do stat = double("stats", :ino => 5) allow(stat).to receive(:uid).and_return(501) allow(stat).to receive(:gid).and_return(501) allow(stat).to receive(:mode).and_return(0755) allow(provider.file_class).to receive(:stat).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(stat) allow(File).to receive(:exists?).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(true) allow(provider.file_class).to receive(:symlink?).with("#{CHEF_SPEC_DATA}/fofile-link").and_return(false) end describe "and the source does not exist" do before do allow(File).to receive(:exists?).with("#{CHEF_SPEC_DATA}/fofile").and_return(false) provider.load_current_resource end it "should set the symlink target" do expect(provider.current_resource.target_file).to eq("#{CHEF_SPEC_DATA}/fofile-link") end it "should update the current source of the existing link with an empty string" do expect(provider.current_resource.to).to eq("") end it "should not set the owner" do expect(provider.current_resource.owner).to eq(nil) end it "should not set the group" do expect(provider.current_resource.group).to eq(nil) end end describe "and the source exists" do before do stat = double("stats", :ino => 6) allow(stat).to receive(:uid).and_return(502) allow(stat).to receive(:gid).and_return(502) allow(stat).to receive(:mode).and_return(0644) allow(provider.file_class).to receive(:stat).with("#{CHEF_SPEC_DATA}/fofile").and_return(stat) allow(File).to receive(:exists?).with("#{CHEF_SPEC_DATA}/fofile").and_return(true) provider.load_current_resource end it "should set the symlink target" do expect(provider.current_resource.target_file).to eq("#{CHEF_SPEC_DATA}/fofile-link") end it "should update the current source of the existing link with an empty string" do expect(provider.current_resource.to).to eq("") end it "should not set the owner" do expect(provider.current_resource.owner).to eq(nil) end it "should not set the group" do expect(provider.current_resource.group).to eq(nil) end end describe "and is hardlinked to the source" do before do stat = double("stats", :ino => 5) allow(stat).to receive(:uid).and_return(502) allow(stat).to receive(:gid).and_return(502) allow(stat).to receive(:mode).and_return(0644) allow(provider.file_class).to receive(:stat).with("#{CHEF_SPEC_DATA}/fofile").and_return(stat) allow(File).to receive(:exists?).with("#{CHEF_SPEC_DATA}/fofile").and_return(true) provider.load_current_resource end it "should set the symlink target" do expect(provider.current_resource.target_file).to eq("#{CHEF_SPEC_DATA}/fofile-link") end it "should set the link type" do expect(provider.current_resource.link_type).to eq(:hard) end it "should update the source of the existing link to the link's target" do expect(provider.current_resource.to).to eq(canonicalize("#{CHEF_SPEC_DATA}/fofile")) end it "should not set the owner" do expect(provider.current_resource.owner).to eq(nil) end it "should not set the group" do expect(provider.current_resource.group).to eq(nil) end # We test create in unit tests because there is no other way to ensure # it does no work. Other create and delete scenarios are covered in # the functional tests for links. context "when the desired state is identical" do let(:new_resource) do result = Chef::Resource::Link.new("#{CHEF_SPEC_DATA}/fofile-link") result.to "#{CHEF_SPEC_DATA}/fofile" result.link_type :hard result end it "create does no work" do expect(provider.file_class).not_to receive(:symlink) expect(provider.file_class).not_to receive(:link) expect(provider.access_controls).not_to receive(:set_all) provider.run_action(:create) end end end end end