[Pkg-puppet-devel] [facter] 136/352: (FACT-134) Normalize copies of fact string values

Stig Sandbeck Mathisen ssm at debian.org
Sun Apr 6 22:21:39 UTC 2014


This is an automated email from the git hooks/post-receive script.

ssm pushed a commit to branch master
in repository facter.

commit 95928792b2023577729c34d1bc9c6545ddec8825
Author: Josh Cooper <josh at puppetlabs.com>
Date:   Thu Jan 9 16:37:39 2014 -0800

    (FACT-134) Normalize copies of fact string values
    
    Previously, facter would fail to normalize a frozen, non-UTF8 encoded
    string, such as the value returned by the `rubyversion` fact.
    
    This commit changes the normalization module to make a copy of the
    resolved value, and perform string encoding on that. It also undoes the
    change to Factet::Util::Loader that dup'ed environment variables of the
    form `FACTER_*`.
    
    Paired-with: Andy Parker <andy at puppetlabs.com>
---
 lib/facter/util/loader.rb            |  2 +-
 lib/facter/util/normalization.rb     | 22 +++++++--------
 lib/facter/util/resolution.rb        |  2 --
 spec/unit/util/normalization_spec.rb | 52 +++++++++++++++++++++---------------
 spec/unit/util/resolution_spec.rb    | 29 +++++++++++---------
 5 files changed, 56 insertions(+), 51 deletions(-)

diff --git a/lib/facter/util/loader.rb b/lib/facter/util/loader.rb
index f08a971..a8fb88d 100644
--- a/lib/facter/util/loader.rb
+++ b/lib/facter/util/loader.rb
@@ -141,7 +141,7 @@ class Facter::Util::Loader
 
       Facter.add($1) do
         has_weight 1_000_000
-        setcode { value.dup }
+        setcode { value }
       end
 
       # Short-cut, if we are only looking for one value.
diff --git a/lib/facter/util/normalization.rb b/lib/facter/util/normalization.rb
index 693deb8..f3149f6 100644
--- a/lib/facter/util/normalization.rb
+++ b/lib/facter/util/normalization.rb
@@ -15,7 +15,7 @@ module Facter
       def normalize(value)
         case value
         when Integer, Float, TrueClass, FalseClass, NilClass
-          true
+          value
         when String
           normalize_string(value)
         when Array
@@ -52,20 +52,19 @@ module Facter
           if converted != value
             raise NormalizationError, "String #{value.inspect} is not valid UTF-8"
           end
+          value
         end
       else
         def normalize_string(value)
-          unless value.encoding == Encoding::UTF_8
-            begin
-              value.encode!(Encoding::UTF_8)
-            rescue EncodingError
-              raise NormalizationError, "String encoding #{value.encoding} is not UTF-8 and could not be converted to UTF-8"
-            end
-          end
+          value = value.encode(Encoding::UTF_8)
 
           unless value.valid_encoding?
             raise NormalizationError, "String #{value.inspect} doesn't match the reported encoding #{value.encoding}"
           end
+
+          value
+        rescue EncodingError
+          raise NormalizationError, "String encoding #{value.encoding} is not UTF-8 and could not be converted to UTF-8"
         end
       end
 
@@ -76,7 +75,7 @@ module Facter
       # @param value [Array]
       # @return [void]
       def normalize_array(value)
-        value.each do |elem|
+        value.collect do |elem|
           normalize(elem)
         end
       end
@@ -88,10 +87,7 @@ module Facter
       # @param value [Hash]
       # @return [void]
       def normalize_hash(value)
-        value.each_pair do |k, v|
-          normalize(k)
-          normalize(v)
-        end
+        Hash[value.collect { |k, v| [ normalize(k), normalize(v) ] } ]
       end
     end
   end
diff --git a/lib/facter/util/resolution.rb b/lib/facter/util/resolution.rb
index 140e60b..4160c9b 100644
--- a/lib/facter/util/resolution.rb
+++ b/lib/facter/util/resolution.rb
@@ -442,8 +442,6 @@ class Facter::Util::Resolution
     Facter.show_time "#{self.name}: #{"%.2f" % ms}ms"
 
     Facter::Util::Normalization.normalize(result)
-
-    return result
   rescue Facter::Util::Normalization::NormalizationError => e
     Facter.warn "Fact resolution #{self.name} resolved to an invalid value: #{e.message}"
     nil
diff --git a/spec/unit/util/normalization_spec.rb b/spec/unit/util/normalization_spec.rb
index 9e7cb0e..34f9d10 100644
--- a/spec/unit/util/normalization_spec.rb
+++ b/spec/unit/util/normalization_spec.rb
@@ -7,23 +7,38 @@ describe Facter::Util::Normalization do
 
   subject { described_class }
 
+  def utf16(str)
+    str.encode(Encoding::UTF_16LE)
+  end
+
+  def utf8(str)
+    str.encode(Encoding::UTF_8)
+  end
+
   describe "validating strings" do
     describe "and string encoding is supported", :if => String.instance_methods.include?(:encoding) do
       it "accepts strings that are ASCII and match their encoding and converts them to UTF-8" do
         str = "ASCII".encode(Encoding::ASCII)
-        subject.normalize(str)
-        expect(str.encoding).to eq(Encoding::UTF_8)
+        normalized_str = subject.normalize(str)
+        expect(normalized_str.encoding).to eq(Encoding::UTF_8)
       end
 
       it "accepts strings that are UTF-8 and match their encoding" do
         str = "let's make a ☃!".encode(Encoding::UTF_8)
-        subject.normalize(str)
+        expect(subject.normalize(str)).to eq(str)
       end
 
       it "converts valid non UTF-8 strings to UTF-8" do
         str = "let's make a ☃!".encode(Encoding::UTF_16LE)
-        subject.normalize(str)
-        expect(str.encoding).to eq(Encoding::UTF_8)
+        enc = subject.normalize(str).encoding
+        expect(enc).to eq(Encoding::UTF_8)
+      end
+
+      it "normalizes a frozen string returning a non-frozen string" do
+        str = "factvalue".encode(Encoding::UTF_16LE).freeze
+        normalized_str = subject.normalize(str)
+        expect(normalized_str.encoding).to eq(Encoding::UTF_8)
+        expect(normalized_str).to_not be_frozen
       end
 
       it "rejects strings that are not UTF-8 and do not match their claimed encoding" do
@@ -44,7 +59,7 @@ describe Facter::Util::Normalization do
     describe "and string encoding is not supported", :unless => String.instance_methods.include?(:encoding) do
       it "accepts strings that are UTF-8 and match their encoding" do
         str = "let's make a ☃!"
-        subject.normalize(str)
+        expect(subject.normalize(str)).to eq(str)
       end
 
       it "rejects strings that are not UTF-8" do
@@ -56,34 +71,27 @@ describe Facter::Util::Normalization do
     end
   end
 
-  describe "validating arrays" do
+  describe "normalizing arrays" do
     it "normalizes each element in the array" do
-      arr = ['first', 'second', ['third', 'fourth']]
+      arr = [utf16('first'), utf16('second'), [utf16('third'), utf16('fourth')]]
+      expected_arr = [utf8('first'), utf8('second'), [utf8('third'), utf8('fourth')]]
 
-      subject.expects(:normalize).with('first')
-      subject.expects(:normalize).with('second')
-      subject.expects(:normalize).with(['third', 'fourth'])
-
-      subject.normalize_array(arr)
+      expect(subject.normalize_array(arr)).to eq(expected_arr)
     end
   end
 
-  describe "validating hashes" do
+  describe "normalizing hashes" do
     it "normalizes each element in the array" do
-      hsh = {'first' => 'second', 'third' => ['fourth', 'fifth']}
-
-      subject.expects(:normalize).with('first')
-      subject.expects(:normalize).with('second')
-      subject.expects(:normalize).with('third')
-      subject.expects(:normalize).with(['fourth', 'fifth'])
+      hsh = {utf16('first') => utf16('second'), utf16('third') => [utf16('fourth'), utf16('fifth')]}
+      expected_hsh = {utf8('first') => utf8('second'), utf8('third') => [utf8('fourth'), utf8('fifth')]}
 
-      subject.normalize_hash(hsh)
+      expect(subject.normalize_hash(hsh)).to eq(expected_hsh)
     end
   end
 
   [1, 1.0, true, false, nil].each do |val|
     it "accepts #{val.inspect}:#{val.class}" do
-      subject.normalize(val)
+      expect(subject.normalize(val)).to eq(val)
     end
   end
 
diff --git a/spec/unit/util/resolution_spec.rb b/spec/unit/util/resolution_spec.rb
index 51767df..755b252 100755
--- a/spec/unit/util/resolution_spec.rb
+++ b/spec/unit/util/resolution_spec.rb
@@ -181,6 +181,8 @@ describe Facter::Util::Resolution do
   end
 
   describe "when returning the value" do
+    let(:utf16_string) { "".encode(Encoding::UTF_16LE).freeze }
+
     before do
       @resolve = Facter::Util::Resolution.new("yay")
     end
@@ -210,11 +212,12 @@ describe Facter::Util::Resolution do
           @resolve.value.should == "yup"
         end
 
-        it "it validates the resolved value" do
+        it "it normalizes the resolved value" do
           @resolve.setcode "/bin/foo"
-          Facter::Util::Resolution.expects(:exec).once.returns ""
-          Facter::Util::Normalization.expects(:normalize).with ""
-          @resolve.value.should eq ""
+
+          Facter::Util::Resolution.expects(:exec).once.returns(utf16_string)
+
+          expect(@resolve.value).to eq(utf16_string.encode(Encoding::UTF_8))
         end
       end
 
@@ -230,11 +233,12 @@ describe Facter::Util::Resolution do
           @resolve.value.should == "yup"
         end
 
-        it "it validates the resolved value" do
+        it "it normalizes the resolved value" do
           @resolve.setcode "/bin/foo"
-          Facter::Util::Resolution.expects(:exec).once.returns ""
-          Facter::Util::Normalization.expects(:normalize).with ""
-          @resolve.value.should eq ""
+
+          Facter::Util::Resolution.expects(:exec).once.returns(utf16_string)
+
+          expect(@resolve.value).to eq(utf16_string.encode(Encoding::UTF_8))
         end
       end
     end
@@ -251,11 +255,10 @@ describe Facter::Util::Resolution do
         @resolve.value.should == "yayness"
       end
 
-      it "it validates the resolved value" do
-        @resolve.setcode "/bin/foo"
-        Facter::Util::Resolution.expects(:exec).once.returns ""
-        Facter::Util::Normalization.expects(:normalize).with ""
-        @resolve.value.should eq ""
+      it "it normalizes the resolved value" do
+        @resolve.setcode { utf16_string }
+
+        expect(@resolve.value).to eq(utf16_string.encode(Encoding::UTF_8))
       end
 
       it "should use its limit method to determine the timeout, to avoid conflict when a 'timeout' method exists for some other reason" do

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-puppet/facter.git



More information about the Pkg-puppet-devel mailing list