text: // Copyright 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
  
  package test
  
  import (
  	"encoding/json"
  	"fmt"
  	"testing"
  
  	"github.com/stretchr/testify/assert"
  )
  
  // Asserts two JSON files are semantically equal
  // (ignores white-space and attribute order)
  func AssertJsonsEqual(t *testing.T, expectedJson []byte, actualJson []byte) {
  	result, err := areJsonsEqual(expectedJson, actualJson)
  	if err != nil {
  		t.Errorf("json comparison failed. EXPECTED json: %s\n\n ACTUAL json: %s\n\n . Error details: %s",
  			string(expectedJson), string(actualJson), err)
  	}
  
  	assert.True(t, result)
  }
  
  func areJsonsEqual(expectedJson []byte, actualJson []byte) (bool, error) {
  
  	expectedMap, err := unmarshalToMap(expectedJson)
  	if err != nil {
  		return false, fmt.Errorf("failed to unmarshal to map. details: %s", err)
  	}
  
  	actualMap, err := unmarshalToMap(actualJson)
  	if err != nil {
  		return false, fmt.Errorf("failed to unmarshal to map. details: %s", err)
  	}
  
  	return areMapsEqual(expectedMap, actualMap), nil
  }
  
  func unmarshalToMap(inputJson []byte) (map[string]interface{}, error) {
  	var m map[string]interface{}
  	if err := json.Unmarshal(inputJson, &m); err != nil {
  		return nil, err
  	}
  
  	return m, nil
  }
  
  func areMapsEqual(map1 map[string]interface{}, map2 map[string]interface{}) bool {
  	if map1 == nil || map2 == nil {
  		return false
  	}
  
  	if len(map1) != len(map2) {
  		return false
  	}
  
  	for k, v1 := range map1 {
  		v2, found := map2[k]
  		if !found {
  			return false
  		}
  
  		switch v1 := v1.(type) {
  		case []interface{}:
  			// compare lists
  			if !areListsEqual(v1, v2.([]interface{})) {
  				return false
  			}
  		case map[string]interface{}:
  			// compare maps
  			if !areMapsEqual(v1, v2.(map[string]interface{})) {
  				return false
  			}
  		default:
  			if v1 != v2 {
  				return false
  			}
  		}
  	}
  
  	return true
  }
  
  func areListsEqual(list1 []interface{}, list2 []interface{}) bool {
  	if list1 == nil || list2 == nil {
  		return false
  	}
  
  	if len(list1) != len(list2) {
  		return false
  	}
  
  	for index := range list1 {
  
  		v1 := list1[index]
  		v2 := list2[index]
  
  		switch v1 := v1.(type) {
  		case []interface{}:
  			// compare lists
  			if !areListsEqual(v1, v2.([]interface{})) {
  				return false
  			}
  		case map[string]interface{}:
  			// compare maps
  			if !areMapsEqual(v1, v2.(map[string]interface{})) {
  				return false
  			}
  		default:
  			if v1 != v2 {
  				return false
  			}
  		}
  	}
  
  	return true
  }
  