From 2128506f34073a0f176e02b5fc1a118d05aea51e Mon Sep 17 00:00:00 2001 From: Modestas Vainius Date: Fri, 25 Mar 2016 16:30:10 +0200 Subject: [PATCH] Fix fuzzy_compare to properly work with arrays. Actually this is a rewrite of fuzzy_compare which primarily make it work with arrays. Current implementation was not correct with more than one element in the array. What is more, I believe that when comparing kubernetes descriptors we should compare arrays by their content *ignoring element order*. That's because kubernetes will reorder elements in arrays (I can't think of a case where element order is significant) after initial descriptor upload. Based on https://github.com/garethr/garethr-kubernetes/commit/accf0b5b279d88fd0edd91ac0a70984894fe5ffc --- .../files/swagger/fuzzy_compare.rb | 59 ++++++++----------- 1 file changed, 26 insertions(+), 33 deletions(-) diff --git a/lib/puppet-swagger-generator/files/swagger/fuzzy_compare.rb b/lib/puppet-swagger-generator/files/swagger/fuzzy_compare.rb index e82a2aa..19384f9 100644 --- a/lib/puppet-swagger-generator/files/swagger/fuzzy_compare.rb +++ b/lib/puppet-swagger-generator/files/swagger/fuzzy_compare.rb @@ -9,42 +9,35 @@ class Utils def self.fuzzy_compare(existing, intended) normalized_is = existing.symbolize_keys.fixnumify normalized_should = intended.symbolize_keys.fixnumify - if normalized_is.respond_to? :all? and normalized_is.all? { |k,v| v.class == String } - diff = normalized_is.merge(normalized_should) - diff == normalized_is - elsif normalized_is == normalized_should - true - else - tests = test_complex_structure(normalized_should, normalized_is) - tests.flatten.compact.all? - end + do_compare(normalized_should, normalized_is) end - def self.test_complex_structure(normalized_should, normalized_is) - normalized_should.keys.collect do |key| - klass = normalized_is[key].class - if [String, Fixnum].include? klass - normalized_is[key].to_s == normalized_should[key].to_s - elsif klass == Array - normalized_is[key].collect do |is_value| - normalized_should[key].collect do |should_value| - diff = if is_value.class == Hash - is_value.merge(should_value) - else - should_value - end - diff == is_value - end - end - elsif klass == Hash - diff = normalized_is[key].merge(normalized_should[key]) - if diff == normalized_is[key] - true - else - normalized_should[key].keys.collect do |inner_key| - test_complex_structure(normalized_should[key][inner_key], normalized_is[key][inner_key]) - end + + private + def self.do_compare(normalized_should, normalized_is) + klass = normalized_should.class + if [String, Fixnum, TrueClass, FalseClass].include? klass + normalized_should.to_s == normalized_is.to_s + elsif klass == Array + if normalized_is.class != Array || normalized_should.length != normalized_is.length + false + else + # We want to check that both arrays have the same elements regardless of their order + should_matched = Array.new(normalized_should.length) + tests = normalized_is.collect do |is_value| + normalized_should.lazy.each_with_index.collect do |should_value, i| + should_matched[i] = should_matched[i] || do_compare(should_value, is_value) + end.any? end + tests.flatten.compact.all? + end + elsif klass == Hash + if normalized_is.class != Hash + false + else + normalized_should.lazy.all? { |key, should_value| do_compare(should_value, normalized_is[key]) } end + else + raise "Don't know how to compare object '#{normalized_should}' of class #{klass}" end end end