github.com/coyove/sdss@v0.0.0-20231129015646-c2ec58cca6a2/future/chrony/client_test.go (about) 1 /* 2 Copyright (c) Facebook, Inc. and its affiliates. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package chrony 18 19 import ( 20 "bytes" 21 "encoding/binary" 22 "fmt" 23 "net" 24 "testing" 25 26 "github.com/stretchr/testify/require" 27 ) 28 29 // fakeConn gives us fake io.ReadWriter interacted implementation for which we can provide fake outputs 30 type fakeConn struct { 31 readCount int 32 outputs []*bytes.Buffer 33 } 34 35 func newConn(outputs []*bytes.Buffer) *fakeConn { 36 return &fakeConn{ 37 readCount: 0, 38 outputs: outputs, 39 } 40 } 41 42 func (c *fakeConn) Read(p []byte) (n int, err error) { 43 pos := c.readCount 44 if c.readCount < len(c.outputs) { 45 c.readCount++ 46 return c.outputs[pos].Read(p) 47 } 48 return 0, fmt.Errorf("EOF") 49 } 50 51 func (c *fakeConn) Write(p []byte) (n int, err error) { 52 // here we may assert writes 53 return 0, nil 54 } 55 56 // Test if we have errors when there is nothing on the line to read 57 func TestCommunicateEOF(t *testing.T) { 58 conn := newConn([]*bytes.Buffer{ 59 bytes.NewBuffer([]byte{}), 60 }) 61 client := Client{Sequence: 1, Connection: conn} 62 _, err := client.Communicate(NewTrackingPacket()) 63 require.Error(t, err) 64 } 65 66 func TestCommunicateError(t *testing.T) { 67 var err error 68 buf := &bytes.Buffer{} 69 packetHead := ReplyHead{ 70 Version: protoVersionNumber, 71 PKTType: pktTypeCmdReply, 72 Res1: 0, 73 Res2: 0, 74 Command: reqTracking, 75 Reply: rpyTracking, 76 Status: sttNoSuchSource, 77 Pad1: 0, 78 Pad2: 0, 79 Pad3: 0, 80 Sequence: 2, 81 Pad4: 0, 82 Pad5: 0, 83 } 84 packetBody := replyTrackingContent{} 85 err = binary.Write(buf, binary.BigEndian, packetHead) 86 require.NoError(t, err) 87 err = binary.Write(buf, binary.BigEndian, packetBody) 88 require.NoError(t, err) 89 conn := newConn([]*bytes.Buffer{ 90 buf, 91 }) 92 client := Client{Sequence: 1, Connection: conn} 93 _, err = client.Communicate(NewTrackingPacket()) 94 require.Error(t, err) 95 } 96 97 // Test if we can read reply properly 98 func TestCommunicateOK(t *testing.T) { 99 var err error 100 buf := &bytes.Buffer{} 101 packetHead := ReplyHead{ 102 Version: protoVersionNumber, 103 PKTType: pktTypeCmdReply, 104 Res1: 0, 105 Res2: 0, 106 Command: reqTracking, 107 Reply: rpyTracking, 108 Status: sttSuccess, 109 Pad1: 0, 110 Pad2: 0, 111 Pad3: 0, 112 Sequence: 2, 113 Pad4: 0, 114 Pad5: 0, 115 } 116 packetBody := replyTrackingContent{ 117 RefID: 1, 118 IPAddr: *newIPAddr(net.IP([]byte{192, 168, 0, 10})), 119 Stratum: 3, 120 LeapStatus: 0, 121 RefTime: timeSpec{}, 122 CurrentCorrection: 0, 123 LastOffset: 12345, 124 RMSOffset: 0, 125 FreqPPM: 0, 126 ResidFreqPPM: 0, 127 SkewPPM: 0, 128 RootDelay: 0, 129 RootDispersion: 0, 130 LastUpdateInterval: 0, 131 } 132 err = binary.Write(buf, binary.BigEndian, packetHead) 133 require.NoError(t, err) 134 err = binary.Write(buf, binary.BigEndian, packetBody) 135 require.NoError(t, err) 136 conn := newConn([]*bytes.Buffer{ 137 buf, 138 }) 139 client := Client{Sequence: 1, Connection: conn} 140 p, err := client.Communicate(NewTrackingPacket()) 141 require.NoError(t, err) 142 expected := &ReplyTracking{ 143 ReplyHead: packetHead, 144 Tracking: Tracking{ 145 RefID: packetBody.RefID, 146 IPAddr: net.IP([]byte{192, 168, 0, 10}), 147 Stratum: packetBody.Stratum, 148 LeapStatus: packetBody.LeapStatus, 149 RefTime: packetBody.RefTime.ToTime(), 150 CurrentCorrection: packetBody.CurrentCorrection.ToFloat(), 151 LastOffset: packetBody.LastOffset.ToFloat(), 152 RMSOffset: packetBody.RMSOffset.ToFloat(), 153 FreqPPM: packetBody.FreqPPM.ToFloat(), 154 ResidFreqPPM: packetBody.ResidFreqPPM.ToFloat(), 155 SkewPPM: packetBody.SkewPPM.ToFloat(), 156 RootDelay: packetBody.RootDelay.ToFloat(), 157 RootDispersion: packetBody.RootDispersion.ToFloat(), 158 LastUpdateInterval: packetBody.LastUpdateInterval.ToFloat(), 159 }, 160 } 161 require.Equal(t, expected, p) 162 }