func StatsdInputSpec(c gs.Context) { t := &pipeline_ts.SimpleT{} ctrl := gomock.NewController(t) defer ctrl.Finish() pConfig := NewPipelineConfig(nil) ith := new(plugins_ts.InputTestHelper) ith.Msg = pipeline_ts.GetTestMessage() ith.Pack = NewPipelinePack(pConfig.InputRecycleChan()) ith.PackSupply = make(chan *PipelinePack, 1) // Specify localhost, but we're not really going to use the network ith.AddrStr = "localhost:55565" ith.ResolvedAddrStr = "127.0.0.1:55565" // set up mock helper, input runner, and stat accumulator ith.MockHelper = NewMockPluginHelper(ctrl) ith.MockInputRunner = NewMockInputRunner(ctrl) mockStatAccum := NewMockStatAccumulator(ctrl) c.Specify("A StatsdInput", func() { statsdInput := StatsdInput{} config := statsdInput.ConfigStruct().(*StatsdInputConfig) config.Address = ith.AddrStr err := statsdInput.Init(config) c.Assume(err, gs.IsNil) realListener := statsdInput.listener c.Expect(realListener.LocalAddr().String(), gs.Equals, ith.ResolvedAddrStr) realListener.Close() mockListener := pipeline_ts.NewMockConn(ctrl) statsdInput.listener = mockListener ith.MockHelper.EXPECT().StatAccumulator("StatAccumInput").Return(mockStatAccum, nil) mockListener.EXPECT().Close() mockListener.EXPECT().SetReadDeadline(gomock.Any()) c.Specify("sends a Stat to the StatAccumulator", func() { statName := "sample.count" statVal := 303 msg := fmt.Sprintf("%s:%d|c\n", statName, statVal) expected := Stat{statName, strconv.Itoa(statVal), "c", float32(1)} mockStatAccum.EXPECT().DropStat(expected).Return(true) readCall := mockListener.EXPECT().Read(make([]byte, 512)) readCall.Return(len(msg), nil) readCall.Do(func(msgBytes []byte) { copy(msgBytes, []byte(msg)) statsdInput.Stop() }) var wg sync.WaitGroup wg.Add(1) go func() { err = statsdInput.Run(ith.MockInputRunner, ith.MockHelper) c.Expect(err, gs.IsNil) wg.Done() }() wg.Wait() }) }) }
func TcpInputSpec(c gs.Context) { t := &pipeline_ts.SimpleT{} ctrl := gomock.NewController(t) defer ctrl.Finish() config := NewPipelineConfig(nil) ith := new(plugins_ts.InputTestHelper) ith.Msg = pipeline_ts.GetTestMessage() ith.Pack = NewPipelinePack(config.InputRecycleChan()) ith.AddrStr = "localhost:55565" ith.ResolvedAddrStr = "127.0.0.1:55565" // set up mock helper, decoder set, and packSupply channel ith.MockHelper = pipelinemock.NewMockPluginHelper(ctrl) ith.MockInputRunner = pipelinemock.NewMockInputRunner(ctrl) ith.Decoder = pipelinemock.NewMockDecoderRunner(ctrl) ith.PackSupply = make(chan *PipelinePack, 1) ith.DecodeChan = make(chan *PipelinePack) key := "testkey" signers := map[string]Signer{"test_1": {key}} signer := "test" c.Specify("A TcpInput protobuf parser", func() { ith.MockInputRunner.EXPECT().Name().Return("TcpInput") tcpInput := TcpInput{} err := tcpInput.Init(&TcpInputConfig{Net: "tcp", Address: ith.AddrStr, Signers: signers, Decoder: "ProtobufDecoder", ParserType: "message.proto"}) c.Assume(err, gs.IsNil) realListener := tcpInput.listener c.Expect(realListener.Addr().String(), gs.Equals, ith.ResolvedAddrStr) realListener.Close() mockConnection := pipeline_ts.NewMockConn(ctrl) mockListener := pipeline_ts.NewMockListener(ctrl) tcpInput.listener = mockListener addr := new(address) addr.str = "123" mockConnection.EXPECT().RemoteAddr().Return(addr) mbytes, _ := proto.Marshal(ith.Msg) header := &message.Header{} header.SetMessageLength(uint32(len(mbytes))) err = errors.New("connection closed") // used in the read return(s) readCall := mockConnection.EXPECT().Read(gomock.Any()) readEnd := mockConnection.EXPECT().Read(gomock.Any()).After(readCall) readEnd.Return(0, err) mockConnection.EXPECT().SetReadDeadline(gomock.Any()).Return(nil).AnyTimes() mockConnection.EXPECT().Close() neterr := pipeline_ts.NewMockError(ctrl) neterr.EXPECT().Temporary().Return(false) acceptCall := mockListener.EXPECT().Accept().Return(mockConnection, nil) acceptCall.Do(func() { acceptCall = mockListener.EXPECT().Accept() acceptCall.Return(nil, neterr) }) mockDecoderRunner := ith.Decoder.(*pipelinemock.MockDecoderRunner) mockDecoderRunner.EXPECT().InChan().Return(ith.DecodeChan) ith.MockInputRunner.EXPECT().InChan().Return(ith.PackSupply) enccall := ith.MockHelper.EXPECT().DecoderRunner("ProtobufDecoder", "TcpInput-123-ProtobufDecoder").AnyTimes() enccall.Return(ith.Decoder, true) ith.MockHelper.EXPECT().StopDecoderRunner(ith.Decoder) cleanup := func() { mockListener.EXPECT().Close() tcpInput.Stop() tcpInput.wg.Wait() } c.Specify("reads a message from its connection", func() { hbytes, _ := proto.Marshal(header) buflen := 3 + len(hbytes) + len(mbytes) readCall.Return(buflen, nil) readCall.Do(getPayloadBytes(hbytes, mbytes)) go tcpInput.Run(ith.MockInputRunner, ith.MockHelper) defer cleanup() ith.PackSupply <- ith.Pack packRef := <-ith.DecodeChan c.Expect(ith.Pack, gs.Equals, packRef) c.Expect(string(ith.Pack.MsgBytes), gs.Equals, string(mbytes)) }) c.Specify("reads a MD5 signed message from its connection", func() { header.SetHmacHashFunction(message.Header_MD5) header.SetHmacSigner(signer) header.SetHmacKeyVersion(uint32(1)) hm := hmac.New(md5.New, []byte(key)) hm.Write(mbytes) header.SetHmac(hm.Sum(nil)) hbytes, _ := proto.Marshal(header) buflen := 3 + len(hbytes) + len(mbytes) readCall.Return(buflen, nil) readCall.Do(getPayloadBytes(hbytes, mbytes)) go tcpInput.Run(ith.MockInputRunner, ith.MockHelper) defer cleanup() ith.PackSupply <- ith.Pack timeout := make(chan bool, 1) go func() { time.Sleep(100 * time.Millisecond) timeout <- true }() select { case packRef := <-ith.DecodeChan: c.Expect(ith.Pack, gs.Equals, packRef) c.Expect(string(ith.Pack.MsgBytes), gs.Equals, string(mbytes)) c.Expect(ith.Pack.Signer, gs.Equals, "test") case t := <-timeout: c.Expect(t, gs.IsNil) } }) c.Specify("reads a SHA1 signed message from its connection", func() { header.SetHmacHashFunction(message.Header_SHA1) header.SetHmacSigner(signer) header.SetHmacKeyVersion(uint32(1)) hm := hmac.New(sha1.New, []byte(key)) hm.Write(mbytes) header.SetHmac(hm.Sum(nil)) hbytes, _ := proto.Marshal(header) buflen := 3 + len(hbytes) + len(mbytes) readCall.Return(buflen, nil) readCall.Do(getPayloadBytes(hbytes, mbytes)) go tcpInput.Run(ith.MockInputRunner, ith.MockHelper) defer cleanup() ith.PackSupply <- ith.Pack timeout := make(chan bool, 1) go func() { time.Sleep(100 * time.Millisecond) timeout <- true }() select { case packRef := <-ith.DecodeChan: c.Expect(ith.Pack, gs.Equals, packRef) c.Expect(string(ith.Pack.MsgBytes), gs.Equals, string(mbytes)) c.Expect(ith.Pack.Signer, gs.Equals, "test") case t := <-timeout: c.Expect(t, gs.IsNil) } }) c.Specify("reads a signed message with an expired key from its connection", func() { header.SetHmacHashFunction(message.Header_MD5) header.SetHmacSigner(signer) header.SetHmacKeyVersion(uint32(11)) // non-existent key version hm := hmac.New(md5.New, []byte(key)) hm.Write(mbytes) header.SetHmac(hm.Sum(nil)) hbytes, _ := proto.Marshal(header) buflen := 3 + len(hbytes) + len(mbytes) readCall.Return(buflen, nil) readCall.Do(getPayloadBytes(hbytes, mbytes)) go tcpInput.Run(ith.MockInputRunner, ith.MockHelper) defer cleanup() ith.PackSupply <- ith.Pack timeout := make(chan bool, 1) go func() { time.Sleep(100 * time.Millisecond) timeout <- true }() select { case packRef := <-mockDecoderRunner.InChan(): c.Expect(packRef, gs.IsNil) case t := <-timeout: c.Expect(t, gs.IsTrue) } }) c.Specify("reads a signed message with an incorrect hmac from its connection", func() { header.SetHmacHashFunction(message.Header_MD5) header.SetHmacSigner(signer) header.SetHmacKeyVersion(uint32(1)) hm := hmac.New(md5.New, []byte(key)) hm.Write([]byte("some bytes")) header.SetHmac(hm.Sum(nil)) hbytes, _ := proto.Marshal(header) buflen := 3 + len(hbytes) + len(mbytes) readCall.Return(buflen, nil) readCall.Do(getPayloadBytes(hbytes, mbytes)) go tcpInput.Run(ith.MockInputRunner, ith.MockHelper) defer cleanup() ith.PackSupply <- ith.Pack timeout := make(chan bool, 1) go func() { time.Sleep(100 * time.Millisecond) timeout <- true }() select { case packRef := <-mockDecoderRunner.InChan(): c.Expect(packRef, gs.IsNil) case t := <-timeout: c.Expect(t, gs.IsTrue) } }) }) c.Specify("A TcpInput regexp parser", func() { ith.MockInputRunner.EXPECT().Name().Return("TcpInput") config := &TcpInputConfig{ Net: "tcp", Address: ith.AddrStr, Decoder: "RegexpDecoder", ParserType: "regexp", } tcpInput := TcpInput{} err := tcpInput.Init(config) c.Assume(err, gs.IsNil) realListener := tcpInput.listener c.Expect(realListener.Addr().String(), gs.Equals, ith.ResolvedAddrStr) realListener.Close() mockConnection := pipeline_ts.NewMockConn(ctrl) mockListener := pipeline_ts.NewMockListener(ctrl) tcpInput.listener = mockListener addr := new(address) addr.str = "123" mockConnection.EXPECT().RemoteAddr().Return(addr).Times(2) mbytes := []byte("this is a test message\n") err = errors.New("connection closed") // used in the read return(s) readCall := mockConnection.EXPECT().Read(gomock.Any()) readEnd := mockConnection.EXPECT().Read(gomock.Any()).After(readCall) readEnd.Return(0, err) mockConnection.EXPECT().SetReadDeadline(gomock.Any()).Return(nil).AnyTimes() mockConnection.EXPECT().Close() neterr := pipeline_ts.NewMockError(ctrl) neterr.EXPECT().Temporary().Return(false) acceptCall := mockListener.EXPECT().Accept().Return(mockConnection, nil) acceptCall.Do(func() { acceptCall = mockListener.EXPECT().Accept() acceptCall.Return(nil, neterr) }) mockDecoderRunner := ith.Decoder.(*pipelinemock.MockDecoderRunner) mockDecoderRunner.EXPECT().InChan().Return(ith.DecodeChan) ith.MockInputRunner.EXPECT().InChan().Return(ith.PackSupply) ith.MockInputRunner.EXPECT().Name().Return("logger") enccall := ith.MockHelper.EXPECT().DecoderRunner("RegexpDecoder", "TcpInput-123-RegexpDecoder").AnyTimes() enccall.Return(ith.Decoder, true) ith.MockHelper.EXPECT().StopDecoderRunner(ith.Decoder) c.Specify("reads a message from its connection", func() { readCall.Return(len(mbytes), nil) readCall.Do(getPayloadText(mbytes)) go tcpInput.Run(ith.MockInputRunner, ith.MockHelper) defer func() { mockListener.EXPECT().Close() tcpInput.Stop() tcpInput.wg.Wait() }() ith.PackSupply <- ith.Pack packRef := <-ith.DecodeChan c.Expect(ith.Pack, gs.Equals, packRef) c.Expect(ith.Pack.Message.GetPayload(), gs.Equals, string(mbytes[:len(mbytes)-1])) c.Expect(ith.Pack.Message.GetLogger(), gs.Equals, "logger") c.Expect(ith.Pack.Message.GetHostname(), gs.Equals, "123") }) }) c.Specify("A TcpInput token parser", func() { ith.MockInputRunner.EXPECT().Name().Return("TcpInput") tcpInput := TcpInput{} err := tcpInput.Init(&TcpInputConfig{Net: "tcp", Address: ith.AddrStr, Decoder: "TokenDecoder", ParserType: "token", Delimiter: "\n"}) c.Assume(err, gs.IsNil) realListener := tcpInput.listener c.Expect(realListener.Addr().String(), gs.Equals, ith.ResolvedAddrStr) realListener.Close() mockConnection := pipeline_ts.NewMockConn(ctrl) mockListener := pipeline_ts.NewMockListener(ctrl) tcpInput.listener = mockListener addr := new(address) addr.str = "123" mockConnection.EXPECT().RemoteAddr().Return(addr).Times(2) mbytes := []byte("this is a test message\n") err = errors.New("connection closed") // used in the read return(s) readCall := mockConnection.EXPECT().Read(gomock.Any()) readEnd := mockConnection.EXPECT().Read(gomock.Any()).After(readCall) readEnd.Return(0, err) mockConnection.EXPECT().SetReadDeadline(gomock.Any()).Return(nil).AnyTimes() mockConnection.EXPECT().Close() neterr := pipeline_ts.NewMockError(ctrl) neterr.EXPECT().Temporary().Return(false) acceptCall := mockListener.EXPECT().Accept().Return(mockConnection, nil) acceptCall.Do(func() { acceptCall = mockListener.EXPECT().Accept() acceptCall.Return(nil, neterr) }) mockDecoderRunner := ith.Decoder.(*pipelinemock.MockDecoderRunner) mockDecoderRunner.EXPECT().InChan().Return(ith.DecodeChan) ith.MockInputRunner.EXPECT().InChan().Return(ith.PackSupply) ith.MockInputRunner.EXPECT().Name().Return("logger") enccall := ith.MockHelper.EXPECT().DecoderRunner("TokenDecoder", "TcpInput-123-TokenDecoder").AnyTimes() enccall.Return(ith.Decoder, true) ith.MockHelper.EXPECT().StopDecoderRunner(ith.Decoder) c.Specify("reads a message from its connection", func() { readCall.Return(len(mbytes), nil) readCall.Do(getPayloadText(mbytes)) go tcpInput.Run(ith.MockInputRunner, ith.MockHelper) defer func() { mockListener.EXPECT().Close() tcpInput.Stop() tcpInput.wg.Wait() }() ith.PackSupply <- ith.Pack packRef := <-ith.DecodeChan c.Expect(ith.Pack, gs.Equals, packRef) c.Expect(ith.Pack.Message.GetPayload(), gs.Equals, string(mbytes)) c.Expect(ith.Pack.Message.GetLogger(), gs.Equals, "logger") c.Expect(ith.Pack.Message.GetHostname(), gs.Equals, "123") }) }) c.Specify("A TcpInput using TLS", func() { tcpInput := TcpInput{} config := &TcpInputConfig{ Net: "tcp", Address: ith.AddrStr, ParserType: "token", UseTls: true, } c.Specify("fails to init w/ missing key or cert file", func() { config.Tls = TlsConfig{} err := tcpInput.Init(config) c.Expect(err, gs.Not(gs.IsNil)) }) c.Specify("accepts TLS client connections", func() { ith.MockInputRunner.EXPECT().Name().Return("TcpInput") config.Tls = TlsConfig{ CertFile: "./testsupport/cert.pem", KeyFile: "./testsupport/key.pem", } err := tcpInput.Init(config) c.Expect(err, gs.IsNil) go tcpInput.Run(ith.MockInputRunner, ith.MockHelper) defer func() { tcpInput.Stop() tcpInput.wg.Wait() }() clientConfig := new(tls.Config) clientConfig.InsecureSkipVerify = true conn, err := tls.Dial("tcp", ith.AddrStr, clientConfig) c.Expect(err, gs.IsNil) defer conn.Close() conn.SetWriteDeadline(time.Now().Add(time.Duration(10000))) n, err := conn.Write([]byte("This is a test.")) c.Expect(err, gs.IsNil) c.Expect(n, gs.Equals, len("This is a test.")) }) c.Specify("doesn't accept connections below specified min TLS version", func() { ith.MockInputRunner.EXPECT().Name().Return("TcpInput") config.Tls = TlsConfig{ CertFile: "./testsupport/cert.pem", KeyFile: "./testsupport/key.pem", MinVersion: "TLS12", } err := tcpInput.Init(config) c.Expect(err, gs.IsNil) go tcpInput.Run(ith.MockInputRunner, ith.MockHelper) defer func() { tcpInput.Stop() tcpInput.wg.Wait() time.Sleep(time.Duration(1000)) }() clientConfig := &tls.Config{ InsecureSkipVerify: true, MaxVersion: tls.VersionTLS11, } conn, err := tls.Dial("tcp", ith.AddrStr, clientConfig) c.Expect(conn, gs.IsNil) c.Expect(err, gs.Not(gs.IsNil)) }) }) }
func TcpOutputSpec(c gs.Context) { t := new(pipeline_ts.SimpleT) ctrl := gomock.NewController(t) tmpDir, tmpErr := ioutil.TempDir("", "tcp-tests-") os.MkdirAll(tmpDir, 0777) defer func() { ctrl.Finish() tmpErr = os.RemoveAll(tmpDir) c.Expect(tmpErr, gs.Equals, nil) }() pConfig := NewPipelineConfig(nil) c.Specify("TcpOutput Internals", func() { tcpOutput := new(TcpOutput) tcpOutput.connection = pipeline_ts.NewMockConn(ctrl) msg := pipeline_ts.GetTestMessage() pack := NewPipelinePack(pConfig.InputRecycleChan()) pack.Message = msg pack.Decoded = true c.Specify("SetName", func() { tcpOutput.SetName("this-is a test") c.Expect(tcpOutput.name, gs.Equals, "this_is_a_test") }) c.Specify("fileExists", func() { c.Expect(fileExists(tmpDir), gs.IsTrue) c.Expect(fileExists(filepath.Join(tmpDir, "test.log")), gs.IsFalse) }) c.Specify("extractBufferId", func() { id, err := extractBufferId("555.log") c.Expect(err, gs.IsNil) c.Expect(id, gs.Equals, uint(555)) id, err = extractBufferId("") c.Expect(err, gs.Not(gs.IsNil)) id, err = extractBufferId("a.log") c.Expect(err, gs.Not(gs.IsNil)) }) c.Specify("findBufferId", func() { c.Expect(findBufferId(tmpDir, true), gs.Equals, uint(0)) c.Expect(findBufferId(tmpDir, false), gs.Equals, uint(0)) _, err := os.OpenFile(filepath.Join(tmpDir, "4.log"), os.O_CREATE, 0644) c.Expect(err, gs.IsNil) _, err = os.OpenFile(filepath.Join(tmpDir, "5.log"), os.O_CREATE, 0644) c.Expect(err, gs.IsNil) _, err = os.OpenFile(filepath.Join(tmpDir, "6a.log"), os.O_CREATE, 0644) c.Expect(err, gs.IsNil) c.Expect(findBufferId(tmpDir, false), gs.Equals, uint(4)) c.Expect(findBufferId(tmpDir, true), gs.Equals, uint(5)) }) c.Specify("writeCheckpoint", func() { tcpOutput.checkpointFilename = filepath.Join(tmpDir, "cp.txt") err := tcpOutput.writeCheckpoint(43, 99999) c.Expect(err, gs.IsNil) c.Expect(fileExists(tcpOutput.checkpointFilename), gs.IsTrue) id, offset, err := readCheckpoint(tcpOutput.checkpointFilename) c.Expect(err, gs.IsNil) c.Expect(id, gs.Equals, uint(43)) c.Expect(offset, gs.Equals, int64(99999)) err = tcpOutput.writeCheckpoint(43, 1) c.Expect(err, gs.IsNil) id, offset, err = readCheckpoint(tcpOutput.checkpointFilename) c.Expect(err, gs.IsNil) c.Expect(id, gs.Equals, uint(43)) c.Expect(offset, gs.Equals, int64(1)) tcpOutput.checkpointFile.Close() }) c.Specify("readCheckpoint", func() { cp := filepath.Join(tmpDir, "cp.txt") file, err := os.OpenFile(cp, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0644) c.Expect(err, gs.IsNil) id, offset, err := readCheckpoint(cp) c.Expect(err, gs.Not(gs.IsNil)) file.WriteString("22") id, offset, err = readCheckpoint(cp) c.Expect(err.Error(), gs.Equals, "invalid checkpoint format") file.Seek(0, 0) file.WriteString("aa 22") id, offset, err = readCheckpoint(cp) c.Expect(err.Error(), gs.Equals, "invalid checkpoint id") file.Seek(0, 0) file.WriteString("43 aa") id, offset, err = readCheckpoint(cp) c.Expect(err.Error(), gs.Equals, "invalid checkpoint offset") file.Seek(0, 0) file.WriteString("43 22") file.Close() id, offset, err = readCheckpoint(cp) c.Expect(err, gs.IsNil) c.Expect(id, gs.Equals, uint(43)) c.Expect(offset, gs.Equals, int64(22)) }) c.Specify("writeToNextFile", func() { tcpOutput.checkpointFilename = filepath.Join(tmpDir, "cp.txt") tcpOutput.queue = tmpDir err := tcpOutput.writeToNextFile() c.Expect(err, gs.IsNil) c.Expect(fileExists(getQueueFilename(tcpOutput.queue, tcpOutput.writeId)), gs.IsTrue) tcpOutput.writeFile.WriteString("this is a test item") tcpOutput.writeFile.Close() tcpOutput.writeCheckpoint(tcpOutput.writeId, 10) tcpOutput.checkpointFile.Close() err = tcpOutput.readFromNextFile() buf := make([]byte, 4) n, err := tcpOutput.readFile.Read(buf) c.Expect(n, gs.Equals, 4) c.Expect("test", gs.Equals, string(buf)) tcpOutput.writeFile.Close() tcpOutput.readFile.Close() }) }) c.Specify("TcpOutput", func() { origBaseDir := Globals().BaseDir Globals().BaseDir = tmpDir defer func() { Globals().BaseDir = origBaseDir }() tcpOutput := new(TcpOutput) tcpOutput.SetName("test") config := tcpOutput.ConfigStruct().(*TcpOutputConfig) tcpOutput.Init(config) tickChan := make(chan time.Time) oth := plugins_ts.NewOutputTestHelper(ctrl) oth.MockOutputRunner.EXPECT().Ticker().Return(tickChan) var wg sync.WaitGroup inChan := make(chan *PipelinePack, 1) msg := pipeline_ts.GetTestMessage() pack := NewPipelinePack(pConfig.InputRecycleChan()) pack.Message = msg pack.Decoded = true c.Specify("writes out to the network", func() { inChanCall := oth.MockOutputRunner.EXPECT().InChan().AnyTimes() inChanCall.Return(inChan) collectData := func(ch chan string) { ln, err := net.Listen("tcp", "localhost:9125") if err != nil { ch <- err.Error() return } ch <- "ready" conn, err := ln.Accept() if err != nil { ch <- err.Error() return } b := make([]byte, 1000) n, _ := conn.Read(b) ch <- string(b[0:n]) conn.Close() ln.Close() } ch := make(chan string, 1) // don't block on put go collectData(ch) result := <-ch // wait for server err := tcpOutput.Init(config) c.Assume(err, gs.IsNil) outStr := "Write me out to the network" pack.Message.SetPayload(outStr) go func() { wg.Add(1) c.Expect(err, gs.IsNil) err = tcpOutput.Run(oth.MockOutputRunner, oth.MockHelper) wg.Done() }() inChan <- pack output := false for x := 0; x < 5; x++ { if fileExists(tcpOutput.checkpointFilename) { output = true break } time.Sleep(time.Duration(500) * time.Millisecond) } c.Expect(output, gs.Equals, true) close(inChan) wg.Wait() // wait for close to finish, prevents intermittent test failures matchBytes := make([]byte, 0, 1000) newpack := NewPipelinePack(nil) newpack.Message = msg newpack.Decoded = true newpack.Message.SetPayload(outStr) err = ProtobufEncodeMessage(newpack, &matchBytes) c.Expect(err, gs.IsNil) result = <-ch c.Expect(result, gs.Equals, string(matchBytes)) id, offset, err := readCheckpoint(tcpOutput.checkpointFilename) c.Expect(err, gs.IsNil) c.Expect(id, gs.Equals, uint(1)) c.Expect(offset, gs.Equals, int64(115)) }) c.Specify("far end not initially listening", func() { inChanCall := oth.MockOutputRunner.EXPECT().InChan().AnyTimes() inChanCall.Return(inChan) oth.MockOutputRunner.EXPECT().LogError(gomock.Any()).AnyTimes() err := tcpOutput.Init(config) c.Assume(err, gs.IsNil) outStr := "Write me out to the network" pack.Message.SetPayload(outStr) go func() { wg.Add(1) c.Expect(err, gs.IsNil) err = tcpOutput.Run(oth.MockOutputRunner, oth.MockHelper) wg.Done() }() inChan <- pack output := false for x := 0; x < 5; x++ { if fileExists(getQueueFilename(tcpOutput.queue, tcpOutput.writeId)) { output = true time.Sleep(time.Duration(1) * time.Second) // give the send time to fail break } time.Sleep(time.Duration(500) * time.Millisecond) } c.Expect(output, gs.Equals, true) collectData := func(ch chan string) { ln, err := net.Listen("tcp", "localhost:9125") if err != nil { ch <- err.Error() return } conn, err := ln.Accept() if err != nil { ch <- err.Error() return } b := make([]byte, 1000) n, _ := conn.Read(b) ch <- string(b[0:n]) conn.Close() ln.Close() } ch := make(chan string, 1) // don't block on put go collectData(ch) result := <-ch // wait for server close(inChan) wg.Wait() // wait for close to finish, prevents intermittent test failures matchBytes := make([]byte, 0, 1000) newpack := NewPipelinePack(nil) newpack.Message = msg newpack.Decoded = true newpack.Message.SetPayload(outStr) err = ProtobufEncodeMessage(newpack, &matchBytes) c.Expect(err, gs.IsNil) c.Expect(result, gs.Equals, string(matchBytes)) id, offset, err := readCheckpoint(tcpOutput.checkpointFilename) c.Expect(err, gs.IsNil) c.Expect(id, gs.Equals, uint(1)) c.Expect(offset, gs.Equals, int64(115)) }) }) }