From f72db0c611c4806d2075cd7edba098ce923b018a Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Wed, 5 Feb 2014 16:14:58 -0800 Subject: [PATCH] core: config raises NoMethodError on bad calls once finalized --- lib/vagrant/config/v2/root.rb | 1 + lib/vagrant/plugin/v2/config.rb | 7 +++++++ test/unit/vagrant/config/v2/root_test.rb | 15 +++++++++++++-- test/unit/vagrant/plugin/v2/config_test.rb | 18 +++++++++++++++++- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/lib/vagrant/config/v2/root.rb b/lib/vagrant/config/v2/root.rb index 3d91e3284..85ba6a0ab 100644 --- a/lib/vagrant/config/v2/root.rb +++ b/lib/vagrant/config/v2/root.rb @@ -48,6 +48,7 @@ module Vagrant @keys.each do |_key, instance| instance.finalize! + instance._finalize! end end diff --git a/lib/vagrant/plugin/v2/config.rb b/lib/vagrant/plugin/v2/config.rb index dfdff8e1c..6588f093c 100644 --- a/lib/vagrant/plugin/v2/config.rb +++ b/lib/vagrant/plugin/v2/config.rb @@ -70,6 +70,8 @@ module Vagrant # Capture all bad configuration calls and save them for an error # message later during validation. def method_missing(name, *args, &block) + return super if @__finalized + name = name.to_s name = name[0...-1] if name.end_with?("=") @@ -130,6 +132,11 @@ module Vagrant return [I18n.t("vagrant.config.common.bad_field", :fields => @__invalid_methods.to_a.sort.join(", "))] end + + # An internal finalize call that no subclass should override. + def _finalize! + @__finalized = true + end end end end diff --git a/test/unit/vagrant/config/v2/root_test.rb b/test/unit/vagrant/config/v2/root_test.rb index 824215058..623269205 100644 --- a/test/unit/vagrant/config/v2/root_test.rb +++ b/test/unit/vagrant/config/v2/root_test.rb @@ -41,8 +41,8 @@ describe Vagrant::Config::V2::Root do } end - describe "finalization" do - it "should finalize un-used keys" do + describe "#finalize!" do + it "should call #finalize!" do foo_class = Class.new do attr_accessor :foo @@ -57,6 +57,17 @@ describe Vagrant::Config::V2::Root do instance.foo.foo.should == "SET" end + + it "should call #_finalize!" do + klass = Class.new + + klass.any_instance.should_receive(:finalize!) + klass.any_instance.should_receive(:_finalize!) + + map = { foo: klass } + instance = described_class.new(map) + instance.finalize! + end end describe "validation" do diff --git a/test/unit/vagrant/plugin/v2/config_test.rb b/test/unit/vagrant/plugin/v2/config_test.rb index 6e32c814c..cf4a0ced6 100644 --- a/test/unit/vagrant/plugin/v2/config_test.rb +++ b/test/unit/vagrant/plugin/v2/config_test.rb @@ -12,7 +12,9 @@ describe Vagrant::Plugin::V2::Config do let(:unset_value) { described_class.const_get("UNSET_VALUE") } - describe "merging" do + subject { foo_class.new } + + describe "#merge" do it "should merge by default by simply copying each instance variable" do one = foo_class.new one.one = 2 @@ -57,4 +59,18 @@ describe Vagrant::Plugin::V2::Config do result.instance_variable_get(:@__bar).should be_nil end end + + describe "#method_missing" do + it "returns a DummyConfig object" do + expect(subject.i_should_not_exist). + to be_kind_of(Vagrant::Config::V2::DummyConfig) + end + + it "raises an error if finalized (internally)" do + subject._finalize! + + expect { subject.i_should_not_exist }. + to raise_error(NoMethodError) + end + end end