github.com/graywolf-at-work-2/terraform-vendor@v1.4.5/internal/states/remote/remote_test.go (about) 1 package remote 2 3 import ( 4 "crypto/md5" 5 "encoding/json" 6 "testing" 7 ) 8 9 func TestRemoteClient_noPayload(t *testing.T) { 10 s := &State{ 11 Client: nilClient{}, 12 } 13 if err := s.RefreshState(); err != nil { 14 t.Fatal("error refreshing empty remote state") 15 } 16 } 17 18 // nilClient returns nil for everything 19 type nilClient struct{} 20 21 func (nilClient) Get() (*Payload, error) { return nil, nil } 22 23 func (c nilClient) Put([]byte) error { return nil } 24 25 func (c nilClient) Delete() error { return nil } 26 27 // mockClient is a client that tracks persisted state snapshots only in 28 // memory and also logs what it has been asked to do for use in test 29 // assertions. 30 type mockClient struct { 31 current []byte 32 log []mockClientRequest 33 } 34 35 type mockClientRequest struct { 36 Method string 37 Content map[string]interface{} 38 } 39 40 func (c *mockClient) Get() (*Payload, error) { 41 c.appendLog("Get", c.current) 42 if c.current == nil { 43 return nil, nil 44 } 45 checksum := md5.Sum(c.current) 46 return &Payload{ 47 Data: c.current, 48 MD5: checksum[:], 49 }, nil 50 } 51 52 func (c *mockClient) Put(data []byte) error { 53 c.appendLog("Put", data) 54 c.current = data 55 return nil 56 } 57 58 func (c *mockClient) Delete() error { 59 c.appendLog("Delete", c.current) 60 c.current = nil 61 return nil 62 } 63 64 func (c *mockClient) appendLog(method string, content []byte) { 65 // For easier test assertions, we actually log the result of decoding 66 // the content JSON rather than the raw bytes. Callers are in principle 67 // allowed to provide any arbitrary bytes here, but we know we're only 68 // using this to test our own State implementation here and that always 69 // uses the JSON state format, so this is fine. 70 71 var contentVal map[string]interface{} 72 if content != nil { 73 err := json.Unmarshal(content, &contentVal) 74 if err != nil { 75 panic(err) // should never happen because our tests control this input 76 } 77 } 78 c.log = append(c.log, mockClientRequest{method, contentVal}) 79 } 80 81 // mockClientForcePusher is like mockClient, but also implements 82 // EnableForcePush, allowing testing for this behavior 83 type mockClientForcePusher struct { 84 current []byte 85 force bool 86 log []mockClientRequest 87 } 88 89 func (c *mockClientForcePusher) Get() (*Payload, error) { 90 c.appendLog("Get", c.current) 91 if c.current == nil { 92 return nil, nil 93 } 94 checksum := md5.Sum(c.current) 95 return &Payload{ 96 Data: c.current, 97 MD5: checksum[:], 98 }, nil 99 } 100 101 func (c *mockClientForcePusher) Put(data []byte) error { 102 if c.force { 103 c.appendLog("Force Put", data) 104 } else { 105 c.appendLog("Put", data) 106 } 107 c.current = data 108 return nil 109 } 110 111 // Implements remote.ClientForcePusher 112 func (c *mockClientForcePusher) EnableForcePush() { 113 c.force = true 114 } 115 116 func (c *mockClientForcePusher) Delete() error { 117 c.appendLog("Delete", c.current) 118 c.current = nil 119 return nil 120 } 121 func (c *mockClientForcePusher) appendLog(method string, content []byte) { 122 var contentVal map[string]interface{} 123 if content != nil { 124 err := json.Unmarshal(content, &contentVal) 125 if err != nil { 126 panic(err) // should never happen because our tests control this input 127 } 128 } 129 c.log = append(c.log, mockClientRequest{method, contentVal}) 130 }