#! /usr/bin/env ruby require 'spec_helper' require 'puppet/util/windows' require 'puppet/util/windows/registry' describe Puppet::Util::Windows::Registry, :if => Puppet::Util::Platform.windows? do subject do class TestRegistry include Puppet::Util::Windows::Registry end TestRegistry.new end let(:name) { 'HKEY_LOCAL_MACHINE' } let(:path) { 'Software\Microsoft' } context "#root" do it "should lookup the root hkey" do subject.root(name).should be_instance_of(Win32::Registry::PredefinedKey) end it "should raise for unknown root keys" do expect { subject.root('HKEY_BOGUS') }.to raise_error(Puppet::Error, /Invalid registry key/) end end context "#open" do let(:hkey) { mock 'hklm' } let(:subkey) { stub 'subkey' } before :each do subject.stubs(:root).returns(hkey) end it "should yield the opened the subkey" do hkey.expects(:open).with do |p, _| p.should == path end.yields(subkey) yielded = nil subject.open(name, path) {|reg| yielded = reg} yielded.should == subkey end [described_class::KEY64, described_class::KEY32].each do |access| it "should open the key for read access 0x#{access.to_s(16)}" do mode = described_class::KEY_READ | access hkey.expects(:open).with(path, mode) subject.open(name, path, mode) {|reg| } end end it "should default to KEY64" do hkey.expects(:open).with(path, described_class::KEY_READ | described_class::KEY64) subject.open(hkey, path) {|hkey| } end it "should raise for a path that doesn't exist" do hkey.expects(:keyname).returns('HKEY_LOCAL_MACHINE') hkey.expects(:open).raises(Win32::Registry::Error.new(2)) # file not found expect do subject.open(hkey, 'doesnotexist') {|hkey| } end.to raise_error(Puppet::Error, /Failed to open registry key 'HKEY_LOCAL_MACHINE\\doesnotexist'/) end end context "#values" do let(:key) { stub('uninstall') } it "should return each value's name and data" do key.expects(:each_value).multiple_yields( ['string', 1, 'foo'], ['dword', 4, 0] ) subject.values(key).should == { 'string' => 'foo', 'dword' => 0 } end it "should return an empty hash if there are no values" do key.expects(:each_value) subject.values(key).should == {} end context "when reading non-ASCII values" do # registered trademark symbol let(:data) do str = [0xAE].pack("C") str.force_encoding('US-ASCII') str end def expects_registry_value(array) key.expects(:each_value).multiple_yields(array) subject.values(key).first[1] end # The win32console gem applies this regex to strip out ANSI escape # sequences. If the registered trademark had encoding US-ASCII, # the regex would fail with 'invalid byte sequence in US-ASCII' def strip_ansi_escapes(value) value.sub(/([^\e]*)?\e([\[\(])([0-9\;\=]*)([a-zA-Z@])(.*)/, '\5') end it "encodes REG_SZ according to the current code page" do reg_value = ['string', Win32::Registry::REG_SZ, data] value = expects_registry_value(reg_value) strip_ansi_escapes(value) end it "encodes REG_EXPAND_SZ based on the current code page" do reg_value = ['expand', Win32::Registry::REG_EXPAND_SZ, "%SYSTEMROOT%\\#{data}"] value = expects_registry_value(reg_value) strip_ansi_escapes(value) end it "encodes REG_MULTI_SZ based on the current code page" do reg_value = ['multi', Win32::Registry::REG_MULTI_SZ, ["one#{data}", "two#{data}"]] value = expects_registry_value(reg_value) value.each { |str| strip_ansi_escapes(str) } end it "passes REG_DWORD through" do reg_value = ['dword', Win32::Registry::REG_DWORD, '1'] value = expects_registry_value(reg_value) Integer(value).should == 1 end end end end