github.com/xmidt-org/webpa-common@v1.11.9/device/metadata_test.go (about)

     1  package device
     2  
     3  import (
     4  	"bytes"
     5  	"math/rand"
     6  	"sync"
     7  	"testing"
     8  
     9  	"github.com/spf13/viper"
    10  	"github.com/stretchr/testify/assert"
    11  	"github.com/stretchr/testify/require"
    12  )
    13  
    14  // claims is a convenient base claims structurally repre to use in tests.
    15  // If you need to modify it, make a copy using deepCopyMap()
    16  var claims map[string]interface{}
    17  
    18  func init() {
    19  	// This is an easy way to catch unmarshalling surprises for claims
    20  	// which come from config values.
    21  	rawYamlConfig := []byte(`
    22  claims: 
    23    aud: XMiDT
    24    capabilities: [xmidt, webpa]
    25    custom: rbl
    26    exp: 1594248706
    27    iat: 1591656706
    28    id: 1234
    29    iss: themis
    30    jti: 5LnpSTsPnuh4TA
    31    nbf: 1591656691
    32    partner-id: comcast
    33    sub: "client:supplied"
    34    trust: 100
    35  `)
    36  	v := viper.New()
    37  	v.SetConfigType("yaml")
    38  	err := v.ReadConfig(bytes.NewBuffer(rawYamlConfig))
    39  	if err != nil {
    40  		panic(err)
    41  	}
    42  	v.UnmarshalKey("claims", &claims)
    43  }
    44  
    45  func TestDeviceMetadataDefaultValues(t *testing.T) {
    46  	assert := assert.New(t)
    47  	m := new(Metadata)
    48  
    49  	assert.Empty(m.Claims())
    50  	assert.Empty(m.SessionID())
    51  	assert.Equal(UnknownPartner, m.PartnerIDClaim())
    52  	assert.Zero(m.TrustClaim())
    53  	assert.Nil(m.Load("not-exists"))
    54  }
    55  
    56  func TestDeviceMetadataInitClaims(t *testing.T) {
    57  	assert := assert.New(t)
    58  	inputClaims := deepCopyMap(claims)
    59  	m := new(Metadata)
    60  	m.SetClaims(inputClaims)
    61  
    62  	assert.Equal(inputClaims, m.Claims())
    63  	assert.Equal("comcast", m.PartnerIDClaim())
    64  	assert.Equal(100, m.TrustClaim())
    65  
    66  	// test defensive copy
    67  	inputClaims[TrustClaimKey] = 200
    68  	assert.NotEqual(inputClaims, m.Claims())
    69  }
    70  func TestDeviceMetadataSessionID(t *testing.T) {
    71  	assert := assert.New(t)
    72  	m := new(Metadata)
    73  
    74  	assert.Empty(m.SessionID())
    75  	m.SetSessionID("uuid:123abc")
    76  	m.SetSessionID("oopsiesCalledAgain")
    77  	assert.Equal("uuid:123abc", m.SessionID())
    78  }
    79  
    80  func TestDeviceMetadataReadUpdateClaims(t *testing.T) {
    81  	assert := assert.New(t)
    82  	m := new(Metadata)
    83  	m.SetClaims(claims)
    84  
    85  	assert.Equal(claims, m.Claims())
    86  	assert.Equal("comcast", m.PartnerIDClaim())
    87  	assert.Equal(100, m.TrustClaim())
    88  
    89  	myClaimsCopy := m.ClaimsCopy()
    90  	myClaimsCopy[TrustClaimKey] = 200
    91  	m.SetClaims(myClaimsCopy)
    92  	assert.Equal(myClaimsCopy, m.Claims())
    93  }
    94  
    95  func TestDeviceMetadataUpdateCustomReferenceValue(t *testing.T) {
    96  	assert := assert.New(t)
    97  	require := require.New(t)
    98  	m := new(Metadata)
    99  	accountInfo := map[string]interface{}{
   100  		"user-id":   4500,
   101  		"user-name": "Talaria XMiDT",
   102  	}
   103  	require.True(m.Store("account-info", accountInfo))
   104  
   105  	oldAccountInfo := m.Load("account-info").(map[string]interface{})
   106  	newAccountInfo := deepCopyMap(oldAccountInfo)
   107  	newAccountInfo["user-id"] = 4501
   108  	require.True(m.Store("account-info", newAccountInfo))
   109  	latestAccountInfo := m.Load("account-info").(map[string]interface{})
   110  	assert.Equal(newAccountInfo, latestAccountInfo)
   111  	assert.NotEqual(oldAccountInfo, latestAccountInfo)
   112  }
   113  
   114  func TestDeviceMetadataReservedKeys(t *testing.T) {
   115  	assert := assert.New(t)
   116  	m := new(Metadata)
   117  	for reservedKey := range reservedMetadataKeys {
   118  		before := m.Load(reservedKey)
   119  		assert.False(m.Store(reservedKey, "poison"))
   120  		after := m.Load(reservedKey)
   121  		assert.Equal(before, after)
   122  	}
   123  }
   124  
   125  func BenchmarkMetadataClaimsCopyParallel(b *testing.B) {
   126  	assert := assert.New(b)
   127  	m := new(Metadata)
   128  	m.SetClaims(claims)
   129  	b.RunParallel(func(pb *testing.PB) {
   130  		for pb.Next() {
   131  			assert.Equal(claims, m.ClaimsCopy())
   132  		}
   133  	})
   134  }
   135  func BenchmarkMetadataClaimsUsageParallel(b *testing.B) {
   136  	b.Run("99PercentReads", benchmarkMetadataClaimsUsageParallel99PercentRead)
   137  	b.Run("80PercentReads", benchmarkMetadataClaimsUsageParallel80PercentRead)
   138  	b.Run("70PercentReads", benchmarkMetadataClaimsUsageParallel70PercentRead)
   139  }
   140  
   141  func benchmarkMetadataClaimsUsageParallel99PercentRead(b *testing.B) {
   142  	benchmarkMetadataClaimsUsageParallel(99, b)
   143  }
   144  
   145  func benchmarkMetadataClaimsUsageParallel80PercentRead(b *testing.B) {
   146  	benchmarkMetadataClaimsUsageParallel(80, b)
   147  }
   148  
   149  func benchmarkMetadataClaimsUsageParallel70PercentRead(b *testing.B) {
   150  	benchmarkMetadataClaimsUsageParallel(70, b)
   151  }
   152  
   153  func benchmarkMetadataClaimsUsageParallel(readPercentage int, b *testing.B) {
   154  	var mux sync.Mutex
   155  	assert := assert.New(b)
   156  	m := new(Metadata)
   157  	m.SetClaims(claims)
   158  
   159  	b.RunParallel(func(pb *testing.PB) {
   160  		for pb.Next() {
   161  			v := rand.Intn(100)
   162  			if v < readPercentage {
   163  				m.Claims()
   164  				m.TrustClaim()
   165  			} else {
   166  				mux.Lock()
   167  				myClaimsCopy := m.ClaimsCopy()
   168  				myTrustLevel := myClaimsCopy[TrustClaimKey].(int) + 1
   169  				myClaimsCopy[TrustClaimKey] = myTrustLevel
   170  				m.SetClaims(myClaimsCopy)
   171  				assert.Equal(myTrustLevel, m.TrustClaim())
   172  				mux.Unlock()
   173  			}
   174  		}
   175  	})
   176  }
   177  
   178  func TestDeepCopyMap(t *testing.T) {
   179  	testCases := []struct {
   180  		Name     string
   181  		Input    map[string]interface{}
   182  		Expected map[string]interface{}
   183  	}{
   184  		{
   185  			Name:     "Nil",
   186  			Expected: make(map[string]interface{}),
   187  		},
   188  		{
   189  			Name:     "Empty",
   190  			Input:    make(map[string]interface{}),
   191  			Expected: make(map[string]interface{}),
   192  		},
   193  		{
   194  			Name:     "Simple",
   195  			Input:    map[string]interface{}{"k0": 0, "k1": 1},
   196  			Expected: map[string]interface{}{"k0": 0, "k1": 1},
   197  		},
   198  		{
   199  			Name: "Complex",
   200  			Input: map[string]interface{}{
   201  				"nested": map[string]interface{}{
   202  					"nestedKey": "nestedVal",
   203  				},
   204  				"nestedToCast": map[interface{}]interface{}{
   205  					3: "nestedVal3",
   206  				},
   207  			},
   208  			Expected: map[string]interface{}{
   209  				"nested": map[string]interface{}{
   210  					"nestedKey": "nestedVal",
   211  				},
   212  				"nestedToCast": map[string]interface{}{
   213  					"3": "nestedVal3",
   214  				},
   215  			},
   216  		},
   217  	}
   218  
   219  	for _, testCase := range testCases {
   220  		t.Run(testCase.Name, func(t *testing.T) {
   221  			assert := assert.New(t)
   222  			cpy := deepCopyMap(testCase.Input)
   223  			assert.Equal(cpy, testCase.Expected)
   224  		})
   225  	}
   226  }