You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
5.9 KiB

  1. // Copyright 2017 Tendermint. All rights reserved.
  2. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
  3. package trust
  4. import (
  5. "fmt"
  6. "io/ioutil"
  7. "os"
  8. "testing"
  9. "time"
  10. "github.com/stretchr/testify/assert"
  11. dbm "github.com/tendermint/tmlibs/db"
  12. "github.com/tendermint/tmlibs/log"
  13. )
  14. func TestTrustMetricStoreSaveLoad(t *testing.T) {
  15. dir, err := ioutil.TempDir("", "trust_test")
  16. if err != nil {
  17. panic(err)
  18. }
  19. defer os.Remove(dir)
  20. historyDB := dbm.NewDB("trusthistory", "goleveldb", dir)
  21. config := TrustMetricConfig{
  22. TrackingWindow: 5 * time.Minute,
  23. IntervalLength: 50 * time.Millisecond,
  24. }
  25. // 0 peers saved
  26. store := NewTrustMetricStore(historyDB, config)
  27. store.SetLogger(log.TestingLogger())
  28. store.saveToDB()
  29. // Load the data from the file
  30. store = NewTrustMetricStore(historyDB, config)
  31. store.SetLogger(log.TestingLogger())
  32. store.loadFromDB()
  33. // Make sure we still have 0 entries
  34. assert.Zero(t, store.Size())
  35. // 100 peers
  36. for i := 0; i < 100; i++ {
  37. key := fmt.Sprintf("peer_%d", i)
  38. tm := store.GetPeerTrustMetric(key)
  39. tm.BadEvents(10)
  40. tm.GoodEvents(1)
  41. }
  42. // Check that we have 100 entries and save
  43. assert.Equal(t, 100, store.Size())
  44. // Give the metrics time to process the history data
  45. time.Sleep(1 * time.Second)
  46. // Stop all the trust metrics and save
  47. for _, tm := range store.peerMetrics {
  48. tm.Stop()
  49. }
  50. store.saveToDB()
  51. // Load the data from the DB
  52. store = NewTrustMetricStore(historyDB, config)
  53. store.SetLogger(log.TestingLogger())
  54. store.loadFromDB()
  55. // Check that we still have 100 peers with imperfect trust values
  56. assert.Equal(t, 100, store.Size())
  57. for _, tm := range store.peerMetrics {
  58. assert.NotEqual(t, 1.0, tm.TrustValue())
  59. }
  60. // Stop all the trust metrics
  61. for _, tm := range store.peerMetrics {
  62. tm.Stop()
  63. }
  64. }
  65. func TestTrustMetricStoreConfig(t *testing.T) {
  66. historyDB := dbm.NewDB("", "memdb", "")
  67. config := TrustMetricConfig{
  68. ProportionalWeight: 0.5,
  69. IntegralWeight: 0.5,
  70. }
  71. // Create a store with custom config
  72. store := NewTrustMetricStore(historyDB, config)
  73. store.SetLogger(log.TestingLogger())
  74. // Have the store make us a metric with the config
  75. tm := store.GetPeerTrustMetric("TestKey")
  76. // Check that the options made it to the metric
  77. assert.Equal(t, 0.5, tm.proportionalWeight)
  78. assert.Equal(t, 0.5, tm.integralWeight)
  79. tm.Stop()
  80. }
  81. func TestTrustMetricStoreLookup(t *testing.T) {
  82. historyDB := dbm.NewDB("", "memdb", "")
  83. store := NewTrustMetricStore(historyDB, DefaultConfig())
  84. store.SetLogger(log.TestingLogger())
  85. // Create 100 peers in the trust metric store
  86. for i := 0; i < 100; i++ {
  87. key := fmt.Sprintf("peer_%d", i)
  88. store.GetPeerTrustMetric(key)
  89. // Check that the trust metric was successfully entered
  90. ktm := store.peerMetrics[key]
  91. assert.NotNil(t, ktm, "Expected to find TrustMetric %s but wasn't there.", key)
  92. }
  93. // Stop all the trust metrics
  94. for _, tm := range store.peerMetrics {
  95. tm.Stop()
  96. }
  97. }
  98. func TestTrustMetricStorePeerScore(t *testing.T) {
  99. historyDB := dbm.NewDB("", "memdb", "")
  100. store := NewTrustMetricStore(historyDB, DefaultConfig())
  101. store.SetLogger(log.TestingLogger())
  102. key := "TestKey"
  103. tm := store.GetPeerTrustMetric(key)
  104. // This peer is innocent so far
  105. first := tm.TrustScore()
  106. assert.Equal(t, 100, first)
  107. // Add some undesirable events and disconnect
  108. tm.BadEvents(1)
  109. first = tm.TrustScore()
  110. assert.NotEqual(t, 100, first)
  111. tm.BadEvents(10)
  112. second := tm.TrustScore()
  113. if second > first {
  114. t.Errorf("A greater number of bad events should lower the trust score")
  115. }
  116. store.PeerDisconnected(key)
  117. // We will remember our experiences with this peer
  118. tm = store.GetPeerTrustMetric(key)
  119. assert.NotEqual(t, 100, tm.TrustScore())
  120. tm.Stop()
  121. }
  122. func TestTrustMetricScores(t *testing.T) {
  123. tm := NewMetric()
  124. // Perfect score
  125. tm.GoodEvents(1)
  126. score := tm.TrustScore()
  127. assert.Equal(t, 100, score)
  128. // Less than perfect score
  129. tm.BadEvents(10)
  130. score = tm.TrustScore()
  131. assert.NotEqual(t, 100, score)
  132. tm.Stop()
  133. }
  134. func TestTrustMetricConfig(t *testing.T) {
  135. // 7 days
  136. window := time.Minute * 60 * 24 * 7
  137. config := TrustMetricConfig{
  138. TrackingWindow: window,
  139. IntervalLength: 2 * time.Minute,
  140. }
  141. tm := NewMetricWithConfig(config)
  142. // The max time intervals should be the TrackingWindow / IntervalLen
  143. assert.Equal(t, int(config.TrackingWindow/config.IntervalLength), tm.maxIntervals)
  144. dc := DefaultConfig()
  145. // These weights should still be the default values
  146. assert.Equal(t, dc.ProportionalWeight, tm.proportionalWeight)
  147. assert.Equal(t, dc.IntegralWeight, tm.integralWeight)
  148. tm.Stop()
  149. config.ProportionalWeight = 0.3
  150. config.IntegralWeight = 0.7
  151. tm = NewMetricWithConfig(config)
  152. // These weights should be equal to our custom values
  153. assert.Equal(t, config.ProportionalWeight, tm.proportionalWeight)
  154. assert.Equal(t, config.IntegralWeight, tm.integralWeight)
  155. tm.Stop()
  156. }
  157. func TestTrustMetricStopPause(t *testing.T) {
  158. // Cause time intervals to pass quickly
  159. config := TrustMetricConfig{
  160. TrackingWindow: 5 * time.Minute,
  161. IntervalLength: 10 * time.Millisecond,
  162. }
  163. tm := NewMetricWithConfig(config)
  164. // Allow some time intervals to pass and pause
  165. time.Sleep(50 * time.Millisecond)
  166. tm.Pause()
  167. // Give the pause some time to take place
  168. time.Sleep(10 * time.Millisecond)
  169. first := tm.Copy().numIntervals
  170. // Allow more time to pass and check the intervals are unchanged
  171. time.Sleep(50 * time.Millisecond)
  172. assert.Equal(t, first, tm.numIntervals)
  173. // Get the trust metric activated again
  174. tm.GoodEvents(5)
  175. // Allow some time intervals to pass and stop
  176. time.Sleep(50 * time.Millisecond)
  177. tm.Stop()
  178. // Give the stop some time to take place
  179. time.Sleep(10 * time.Millisecond)
  180. second := tm.Copy().numIntervals
  181. // Allow more time to pass and check the intervals are unchanged
  182. time.Sleep(50 * time.Millisecond)
  183. assert.Equal(t, second, tm.numIntervals)
  184. if first >= second {
  185. t.Fatalf("numIntervals should always increase or stay the same over time")
  186. }
  187. }