func TestAmqp_ChannelCloseErrorMethod(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() data, err := hex.DecodeString("0100010000009000140028019685505245434f4e444" + "954494f4e5f4641494c4544202d20696e6571756976616c656e74206172672027617574" + "6f5f64656c6574652720666f722065786368616e676520277465737445786368616e676" + "52720696e2076686f737420272f273a207265636569766564202774727565272062757" + "42063757272656e74206973202766616c7365270028000ace") assert.Nil(t, err) data2, err := hex.DecodeString("0100010000000400280033ce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} amqp.Parse(&req, tcptuple, 1, private) trans := expectTransaction(t, amqp) assert.Equal(t, "channel.close", trans["method"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, common.ERROR_STATUS, trans["status"]) assert.Nil(t, trans["notes"]) }
func TestAmqp_MultipleBodyFrames(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendRequest = true data, err := hex.DecodeString("0100010000000e003c00280000000568656c6c6f00ce" + "02000100000021003c0000000000000000002a80400a746578742f706c61696e00000000" + "56a22873ce030001000000202a2a2a68656c6c6f2049206c696b6520746f207075626c69" + "736820626967206dce") assert.Nil(t, err) data2, err := hex.DecodeString("0300010000000a657373616765732a2a2ace") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, amqp) assert.Equal(t, "basic.publish", trans["method"]) assert.Equal(t, "***hello I like to publish big messages***", trans["request"]) }
func TestAmqp_ConnectionCloseNoError(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.hideConnectionInformation = false data, err := hex.DecodeString("01000000000012000a003200c8076b74687862616900000000ce") assert.Nil(t, err) data2, err := hex.DecodeString("01000000000004000a0033ce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} amqp.Parse(&req, tcptuple, 1, private) trans := expectTransaction(t, amqp) assert.Equal(t, "connection.close", trans["method"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, common.OK_STATUS, trans["status"]) assert.Nil(t, trans["notes"]) fields, ok := trans["amqp"].(common.MapStr) assert.True(t, ok) code, ok := fields["reply-code"].(uint16) assert.True(t, ok) assert.Equal(t, uint16(200), code) }
func TestAmqp_RejectMessage(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendRequest = true data, err := hex.DecodeString("0100010000000d003c005a000000000000000101ce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) //method frame amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, amqp) assert.Equal(t, "basic.reject", trans["method"]) assert.Equal(t, "basic.reject 1", trans["request"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, common.ERROR_STATUS, trans["status"]) fields, ok := trans["amqp"].(common.MapStr) if !ok { t.Errorf("Field should be present") } assert.Equal(t, true, fields["multiple"]) }
// Verify that a gap during the response publish the request with Notes func TestGapResponse(t *testing.T) { dns := newDns(testing.Verbose()) q := sophosTxtTcp.request r := sophosTxtTcp.response[:10] tcptuple := testTcpTuple() private := protos.ProtocolData(new(dnsPrivateData)) packet := newPacket(forward, q) private = dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) assert.Equal(t, 1, dns.transactions.Size(), "There should be one transaction.") packet = newPacket(reverse, r) private = dns.Parse(packet, tcptuple, tcp.TcpDirectionReverse, private) assert.Equal(t, 1, dns.transactions.Size(), "There should be one transaction.") private, drop := dns.GapInStream(tcptuple, tcp.TcpDirectionReverse, 10, private) assert.Equal(t, true, drop) private = dns.ReceivedFin(tcptuple, tcp.TcpDirectionReverse, private) client := dns.results.(publisher.ChanClient) close(client.Channel) mapStr := <-client.Channel assert.NotNil(t, mapStr, "One result should have been published.") assert.Equal(t, mapStr["notes"], "Response packet's data could not be decoded as DNS.") assert.Nil(t, mapStr["answers"]) }
// parseTcpRequestResponse parses a request then a response packet and validates // the published result. func parseTcpRequestResponse(t testing.TB, dns *Dns, q DnsTestMessage) { packet := newPacket(forward, q.request) tcptuple := testTcpTuple() private := protos.ProtocolData(new(dnsPrivateData)) dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) packet = newPacket(reverse, q.response) dns.Parse(packet, tcptuple, tcp.TcpDirectionReverse, private) assert.Empty(t, dns.transactions.Size(), "There should be no transactions.") m := expectResult(t, dns) assert.Equal(t, "tcp", mapValue(t, m, "transport")) assert.Equal(t, len(q.request), mapValue(t, m, "bytes_in")) assert.Equal(t, len(q.response), mapValue(t, m, "bytes_out")) assert.NotNil(t, mapValue(t, m, "responsetime")) if assert.ObjectsAreEqual("NOERROR", mapValue(t, m, "dns.response_code")) { assert.Equal(t, common.OK_STATUS, mapValue(t, m, "status")) } else { assert.Equal(t, common.ERROR_STATUS, mapValue(t, m, "status")) } assert.Nil(t, mapValue(t, m, "notes")) assertMapStrData(t, m, q) }
func TestAmqp_GetEmptyMethod(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendRequest = true data, err := hex.DecodeString("01000100000013003c004600000b526f626269" + "654b65616e6501ce") assert.Nil(t, err) data2, err := hex.DecodeString("01000100000005003c004800ce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} amqp.Parse(&req, tcptuple, 1, private) trans := expectTransaction(t, amqp) assert.Equal(t, "basic.get-empty", trans["method"]) assert.Equal(t, "basic.get RobbieKeane", trans["request"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, common.OK_STATUS, trans["status"]) }
func TestAmqp_NoWaitQueueDeleteMethod(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendRequest = true data, err := hex.DecodeString("010001000000120032002800000a546573745468" + "6f6d617304ce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, amqp) assert.Equal(t, "queue.delete", trans["method"]) assert.Equal(t, "queue.delete TestThomas", trans["request"]) assert.Equal(t, "amqp", trans["type"]) fields, ok := trans["amqp"].(common.MapStr) if !ok { t.Errorf("Field should be present") } assert.Equal(t, true, fields["no-wait"]) assert.Equal(t, false, fields["if-empty"]) assert.Equal(t, false, fields["if-unused"]) assert.Equal(t, "TestThomas", fields["queue"]) }
func TestAmqp_GetMethod(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendRequest = true amqp.sendResponse = true data, err := hex.DecodeString("0100010000000f003c0046000007546573744" + "7657401ce") assert.Nil(t, err) data2, err := hex.DecodeString("0100010000001a003c00470000000000000001" + "0000075465737447657400000001ce02000100000019003c000000000000000000" + "1280000a746578742f706c61696ece03000100000012476574206d6520696620796" + "f752064617265ce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} amqp.Parse(&req, tcptuple, 1, private) trans := expectTransaction(t, amqp) assert.Equal(t, "basic.get", trans["method"]) assert.Equal(t, "basic.get TestGet", trans["request"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, common.OK_STATUS, trans["status"]) assert.Equal(t, "Get me if you dare", trans["response"]) }
func TestAmqp_RecoverMethod(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendRequest = true data, err := hex.DecodeString("01000100000005003c006e01ce") assert.Nil(t, err) data2, err := hex.DecodeString("01000100000004003c006fce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} amqp.Parse(&req, tcptuple, 1, private) trans := expectTransaction(t, amqp) assert.Equal(t, "basic.recover", trans["method"]) assert.Equal(t, "basic.recover", trans["request"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, common.OK_STATUS, trans["status"]) assert.Equal(t, common.MapStr{"requeue": true}, trans["amqp"]) }
// Benchmarks TCP parsing for the given test message. func benchmarkTcp(b *testing.B, q DnsTestMessage) { dns := newDns(false) for i := 0; i < b.N; i++ { packet := newPacket(forward, q.request) tcptuple := testTcpTuple() private := protos.ProtocolData(new(dnsPrivateData)) dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) packet = newPacket(reverse, q.response) tcptuple = testTcpTuple() private = protos.ProtocolData(new(dnsPrivateData)) dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) client := dns.results.(publisher.ChanClient) <-client.Channel } }
// Verify that a malformed packet is safely handled (no panics). func TestParseTcp_malformedPacket(t *testing.T) { dns := newDns(testing.Verbose()) garbage := []byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13} tcptuple := testTcpTuple() packet := newPacket(forward, garbage) private := protos.ProtocolData(new(dnsPrivateData)) dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) assert.Empty(t, dns.transactions.Size(), "There should be no transactions.") }
// Benchmark that runs with parallelism to help find concurrency related // issues. To run with parallelism, the 'go test' cpu flag must be set // greater than 1, otherwise it just runs concurrently but not in parallel. func BenchmarkParallelTcpParse(b *testing.B) { rand.Seed(22) numMessages := len(messagesTcp) dns := newDns(false) client := dns.results.(publisher.ChanClient) // Drain the results channal while the test is running. go func() { totalMessages := 0 for r := range client.Channel { _ = r totalMessages++ } fmt.Printf("Parsed %d messages.\n", totalMessages) }() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { // Each iteration parses one message, either a request or a response. // The request and response could be parsed on different goroutines. for pb.Next() { q := messagesTcp[rand.Intn(numMessages)] var packet *protos.Packet var tcptuple *common.TcpTuple var private protos.ProtocolData if rand.Intn(2) == 0 { packet = newPacket(forward, q.request) tcptuple = testTcpTuple() private = protos.ProtocolData(new(dnsPrivateData)) } else { packet = newPacket(reverse, q.response) tcptuple = testTcpTuple() private = protos.ProtocolData(new(dnsPrivateData)) } dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) } }) defer close(client.Channel) }
// Verify that the lone request packet is parsed. func TestParseTcp_requestPacket(t *testing.T) { dns := newDns(testing.Verbose()) packet := newPacket(forward, elasticATcp.request) tcptuple := testTcpTuple() private := protos.ProtocolData(new(dnsPrivateData)) dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) assert.Equal(t, 1, dns.transactions.Size(), "There should be one transaction.") client := dns.results.(publisher.ChanClient) close(client.Channel) assert.Nil(t, <-client.Channel, "No result should have been published.") }
func TestThrift_GapInStream_response(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"thrift", "thriftdetailed"}) } var thrift Thrift thrift.Init(true, nil) thrift.Idl = thriftIdlForTesting(t, ` exception InvalidOperation { 1: i32 what, 2: string why } service Test { i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), } `) thrift.PublishQueue = make(chan *ThriftTransaction, 10) tcptuple := testTcpTuple() req := createTestPacket(t, "800100010000000963616c63756c6174650000000008000"+ "1000000010c00020800010000000108000200000000080003000000040000") // missing last few bytes repl := createTestPacket(t, "800100020000000963616c63756c617465000000000c00"+ "01080001000000040b00020000001243616e6e6f742064697669646520") private := protos.ProtocolData(new(thriftPrivateData)) private = thrift.Parse(req, tcptuple, 0, private) private = thrift.Parse(repl, tcptuple, 1, private) private, drop := thrift.GapInStream(tcptuple, 1, 5, private) if drop == false { t.Error("GapInStream returned drop=false") } trans := expectThriftTransaction(t, thrift) // The exception is not captured, but otherwise the values from the request // are correct if trans.Request.Method != "calculate" || trans.Request.Params != "(logid: 1, w: (1: 1, 2: 0, 3: 4))" || trans.Reply.ReturnValue != "" || trans.Reply.Exceptions != `` || trans.Reply.HasException || trans.Request.Service != "Test" || trans.Reply.Notes[0] != "Packet loss while capturing the response" { t.Error("trans.Reply.Exceptions", trans.Reply.Exceptions) t.Error("trans.Reply.HasException", trans.Reply.HasException) } }
// Test that loss of data during the response (but not at the beginning) // don't cause the whole transaction to be dropped. func Test_gap_in_response(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"mysql", "mysqldetailed"}) } mysql := MysqlModForTests() // request and response from tests/pcaps/mysql_result_long.pcap // select * from test req_data, err := hex.DecodeString( "130000000373656c656374202a20" + "66726f6d2074657374") assert.Nil(t, err) resp_data, err := hex.DecodeString( "0100000103240000020364656604" + "74657374047465737404746573740161" + "01610c3f000b00000003000000000024" + "00000303646566047465737404746573" + "740474657374016201620c3f000b0000" + "00030000000000240000040364656604" + "74657374047465737404746573740163" + "01630c2100fd020000fd000000000005" + "000005fe000022000a00000601310131" + "0548656c6c6f0a000007013201320548" + "656c6c6f0601000801330133fcff004c" + "6f72656d20497073756d206973207369" + "6d706c792064756d6d79207465787420" + "6f6620746865207072696e74696e6720" + "616e64207479706573657474696e6720" + "696e6475737472792e204c6f72656d20") assert.Nil(t, err) tcptuple := testTcpTuple() req := protos.Packet{Payload: req_data} resp := protos.Packet{Payload: resp_data} private := protos.ProtocolData(new(mysqlPrivateData)) private = mysql.Parse(&req, tcptuple, 0, private) private = mysql.Parse(&resp, tcptuple, 1, private) logp.Debug("mysql", "Now sending gap..") private, drop := mysql.GapInStream(tcptuple, 1, 10, private) assert.Equal(t, true, drop) trans := expectTransaction(t, mysql) assert.NotNil(t, trans) assert.Equal(t, trans["notes"], []string{"Packet loss while capturing the response"}) }
func TestAmqp_PublishMessage(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendRequest = true data, err := hex.DecodeString("0100010000001b003c002800000a6c6f67735f746f70" + "696308414d51507465737400ce") assert.Nil(t, err) data2, err := hex.DecodeString("02000100000019003c0000000000000000001c800" + "00a746578742f706c61696ece") assert.Nil(t, err) data3, err := hex.DecodeString("0300010000001c48656c6c6f204461726c696e67" + "2049276d20686f6d6520616761696ece") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) //method frame private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} //header frame private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data3} //body frame amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, amqp) body := "Hello Darling I'm home again" assert.Equal(t, "basic.publish", trans["method"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, body, trans["request"]) assert.Equal(t, common.OK_STATUS, trans["status"]) fields, ok := trans["amqp"].(common.MapStr) if !ok { t.Errorf("Field should be present") } assert.Equal(t, "text/plain", fields["content-type"]) assert.Equal(t, "logs_topic", fields["exchange"]) assert.Equal(t, "AMQPtest", fields["routing-key"]) assert.Equal(t, false, fields["immediate"]) assert.Equal(t, false, fields["mandatory"]) }
func BenchmarkHttpSimpleTransaction(b *testing.B) { data1 := "GET / HTTP/1.1\r\n" + "Host: www.google.ro\r\n" + "Connection: keep-alive\r\n" + "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_4) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.75 Safari/537.1\r\n" + "Accept: */*\r\n" + "X-Chrome-Variations: CLa1yQEIj7bJAQiftskBCKS2yQEIp7bJAQiptskBCLSDygE=\r\n" + "Referer: http://www.google.ro/\r\n" + "Accept-Encoding: gzip,deflate,sdch\r\n" + "Accept-Language: en-US,en;q=0.8\r\n" + "Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3\r\n" + "Cookie: PREF=ID=6b67d166417efec4:U=69097d4080ae0e15:FF=0:TM=1340891937:LM=1340891938:S=8t97UBiUwKbESvVX; NID=61=sf10OV-t02wu5PXrc09AhGagFrhSAB2C_98ZaI53-uH4jGiVG_yz9WmE3vjEBcmJyWUogB1ZF5puyDIIiB-UIdLd4OEgPR3x1LHNyuGmEDaNbQ_XaxWQqqQ59mX1qgLQ\r\n" + "\r\n" data2 := "HTTP/1.1 200 OK\r\n" + "Date: Tue, 14 Aug 2012 22:31:45 GMT\r\n" + "Expires: -1\r\n" + "Cache-Control: private, max-age=0\r\n" + "Content-Type: text/html; charset=UTF-8\r\n" + "Content-Encoding: gzip\r\n" + "Server: gws\r\n" + "Content-Length: 0\r\n" + "X-XSS-Protection: 1; mode=block\r\n" + "X-Frame-Options: SAMEORIGIN\r\n" + "\r\n" http := httpModForTests() tcptuple := testCreateTCPTuple() req := protos.Packet{Payload: []byte(data1)} resp := protos.Packet{Payload: []byte(data2)} client := http.results.(*publish.ChanTransactions) for i := 0; i < b.N; i++ { private := protos.ProtocolData(&httpConnectionData{}) private = http.Parse(&req, tcptuple, 0, private) private = http.ReceivedFin(tcptuple, 0, private) private = http.Parse(&resp, tcptuple, 1, private) http.ReceivedFin(tcptuple, 1, private) select { case <-client.Channel: default: b.Error("No transaction returned") } } }
func TestAmqp_DeliverMessage(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendResponse = true data, err := hex.DecodeString("01000100000034003c003c0d6d6973746572436f6e73" + "756d650000000000000002000c7465737445786368616e67650b7465737444656c697" + "66572ce") assert.Nil(t, err) data2, err := hex.DecodeString("02000100000019003c000000000000000000058" + "0000a746578742f706c61696ece") assert.Nil(t, err) data3, err := hex.DecodeString("030001000000056b696b6f6fce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) //method frame private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} //header frame private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data3} //body frame amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, amqp) assert.Equal(t, "basic.deliver", trans["method"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, "kikoo", trans["response"]) assert.Equal(t, common.OK_STATUS, trans["status"]) fields, ok := trans["amqp"].(common.MapStr) if !ok { t.Errorf("Field should be present") } assert.Equal(t, "misterConsume", fields["consumer-tag"]) assert.Equal(t, "text/plain", fields["content-type"]) assert.Equal(t, "testDeliver", fields["routing-key"]) assert.Equal(t, false, fields["redelivered"]) }
// Verify that the lone response packet is parsed and that an error // result is published. func TestParseTcp_responseOnly(t *testing.T) { dns := newDns(testing.Verbose()) q := elasticATcp packet := newPacket(reverse, q.response) tcptuple := testTcpTuple() private := protos.ProtocolData(new(dnsPrivateData)) dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) m := expectResult(t, dns) assert.Equal(t, "tcp", mapValue(t, m, "transport")) assert.Nil(t, mapValue(t, m, "bytes_in")) assert.Equal(t, len(q.response), mapValue(t, m, "bytes_out")) assert.Nil(t, mapValue(t, m, "responsetime")) assert.Equal(t, common.ERROR_STATUS, mapValue(t, m, "status")) assert.Equal(t, OrphanedResponseMsg, mapValue(t, m, "notes")) assertMapStrData(t, m, q) }
func TestThrift_GapInStream_request(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"thrift", "thriftdetailed"}) } var thrift Thrift thrift.Init(true, nil) thrift.Idl = thriftIdlForTesting(t, ` exception InvalidOperation { 1: i32 what, 2: string why } service Test { i32 calculate(1:i32 logid, 2:Work w) throws (1:InvalidOperation ouch), } `) thrift.PublishQueue = make(chan *ThriftTransaction, 10) tcptuple := testTcpTuple() // missing bytes from the request req := createTestPacket(t, "800100010000000963616c63756c6174") repl := createTestPacket(t, "800100020000000963616c63756c617465000000000c00"+ "01080001000000040b00020000001243616e6e6f742064697669646520627920300000") private := protos.ProtocolData(new(thriftPrivateData)) private = thrift.Parse(req, tcptuple, 0, private) private, drop := thrift.GapInStream(tcptuple, 0, 5, private) private = thrift.Parse(repl, tcptuple, 1, private) if drop == false { t.Error("GapInStream returned drop=false") } // packet loss in requests should result in no transaction select { case trans := <-thrift.PublishQueue: t.Error("Expected no transaction but got one:", trans) default: // ok } }
// Test that loss of data during the response (but not at the beginning) // don't cause the whole transaction to be dropped. func Test_gap_in_response(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"pgsql", "pgsqldetailed"}) } pgsql := pgsqlModForTests() // request and response from tests/pcaps/pgsql_request_response.pcap // select * from test reqData, err := hex.DecodeString( "510000001873656c656374202a20" + "66726f6d20746573743b00") assert.Nil(t, err) // response is incomplete respData, err := hex.DecodeString( "5400000042000361000000410900" + "0100000413ffffffffffff0000620000" + "004009000200000413ffffffffffff00" + "00630000004009000300000413ffffff" + "ffffff0000440000001b000300000003" + "6d6561000000036d6562000000036d65" + "63440000001e0003000000046d656131" + "000000046d656231000000046d656331" + "440000001e0003000000046d65613200") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: reqData} resp := protos.Packet{Payload: respData} private := protos.ProtocolData(new(pgsqlPrivateData)) private = pgsql.Parse(&req, tcptuple, 0, private) private = pgsql.Parse(&resp, tcptuple, 1, private) logp.Debug("pgsql", "Now sending gap..") _, drop := pgsql.GapInStream(tcptuple, 1, 10, private) assert.Equal(t, true, drop) trans := expectTransaction(t, pgsql) assert.NotNil(t, trans) assert.Equal(t, trans["notes"], []string{"Packet loss while capturing the response"}) }
func Test_gap_in_body_http1dot0_fin(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"http", "httpdetailed"}) } http := httpModForTests() data1 := []byte("GET / HTTP/1.0\r\n\r\n") data2 := []byte("HTTP/1.0 200 OK\r\n" + "Date: Tue, 14 Aug 2012 22:31:45 GMT\r\n" + "Expires: -1\r\n" + "Cache-Control: private, max-age=0\r\n" + "Content-Type: text/html; charset=UTF-8\r\n" + "Content-Encoding: gzip\r\n" + "Server: gws\r\n" + "X-XSS-Protection: 1; mode=block\r\n" + "X-Frame-Options: SAMEORIGIN\r\n" + "\r\n" + "xxxxxxxxxxxxxxxxxxxx") tcptuple := testCreateTCPTuple() req := protos.Packet{Payload: data1} resp := protos.Packet{Payload: data2} private := protos.ProtocolData(new(httpConnectionData)) private = http.Parse(&req, tcptuple, 0, private) private = http.ReceivedFin(tcptuple, 0, private) private = http.Parse(&resp, tcptuple, 1, private) logp.Debug("http", "Now sending gap..") private, drop := http.GapInStream(tcptuple, 1, 10, private) assert.Equal(t, false, drop) http.ReceivedFin(tcptuple, 1, private) trans := expectTransaction(t, http) assert.NotNil(t, trans) assert.Equal(t, trans["notes"], []string{"Packet loss while capturing the response"}) }
// Verify that the first request is published without a response and that // the status is error. This second packet will remain in the transaction // map awaiting a response. func TestParseTcp_duplicateRequests(t *testing.T) { dns := newDns(testing.Verbose()) q := elasticATcp packet := newPacket(forward, q.request) tcptuple := testTcpTuple() private := protos.ProtocolData(new(dnsPrivateData)) dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) assert.Equal(t, 1, dns.transactions.Size(), "There should be one transaction.") packet = newPacket(forward, q.request) dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) assert.Equal(t, 1, dns.transactions.Size(), "There should be one transaction.") m := expectResult(t, dns) assert.Equal(t, "tcp", mapValue(t, m, "transport")) assert.Equal(t, len(q.request), mapValue(t, m, "bytes_in")) assert.Nil(t, mapValue(t, m, "bytes_out")) assert.Nil(t, mapValue(t, m, "responsetime")) assert.Equal(t, common.ERROR_STATUS, mapValue(t, m, "status")) assert.Equal(t, DuplicateQueryMsg, mapValue(t, m, "notes")) }
func TestGapRequestDrop(t *testing.T) { dns := newDns(testing.Verbose()) q := sophosTxtTcp.request[:10] packet := newPacket(forward, q) tcptuple := testTcpTuple() private := protos.ProtocolData(new(dnsPrivateData)) private = dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) private, drop := dns.GapInStream(tcptuple, tcp.TcpDirectionOriginal, 10, private) assert.Equal(t, true, drop) private = dns.ReceivedFin(tcptuple, tcp.TcpDirectionOriginal, private) client := dns.results.(publisher.ChanClient) close(client.Channel) mapStr := <-client.Channel assert.Nil(t, mapStr, "No result should have been published.") }
// Verify that the split lone request packet is parsed. func TestParseTcpSplitResponse(t *testing.T) { dns := newDns(testing.Verbose()) tcpQuery := elasticATcp q := tcpQuery.request r0 := tcpQuery.response[:10] r1 := tcpQuery.response[10:] tcptuple := testTcpTuple() private := protos.ProtocolData(new(dnsPrivateData)) packet := newPacket(forward, q) private = dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) assert.Equal(t, 1, dns.transactions.Size(), "There should be one transaction.") packet = newPacket(reverse, r0) private = dns.Parse(packet, tcptuple, tcp.TcpDirectionReverse, private) assert.Equal(t, 1, dns.transactions.Size(), "There should be one transaction.") packet = newPacket(reverse, r1) private = dns.Parse(packet, tcptuple, tcp.TcpDirectionReverse, private) assert.Empty(t, dns.transactions.Size(), "There should be no transaction.") m := expectResult(t, dns) assert.Equal(t, "tcp", mapValue(t, m, "transport")) assert.Equal(t, len(tcpQuery.request), mapValue(t, m, "bytes_in")) assert.Equal(t, len(tcpQuery.response), mapValue(t, m, "bytes_out")) assert.NotNil(t, mapValue(t, m, "responsetime")) if assert.ObjectsAreEqual("NOERROR", mapValue(t, m, "dns.response_code")) { assert.Equal(t, common.OK_STATUS, mapValue(t, m, "status")) } else { assert.Equal(t, common.ERROR_STATUS, mapValue(t, m, "status")) } assert.Nil(t, mapValue(t, m, "notes")) assertMapStrData(t, m, tcpQuery) }
// Verify that a gap/fin happening after a valid query create only one tansaction func TestGapFinValidMessage(t *testing.T) { dns := newDns(testing.Verbose()) q := sophosTxtTcp.request tcptuple := testTcpTuple() private := protos.ProtocolData(new(dnsPrivateData)) packet := newPacket(forward, q) private = dns.Parse(packet, tcptuple, tcp.TcpDirectionOriginal, private) assert.Equal(t, 1, dns.transactions.Size(), "There should be one transaction.") private, drop := dns.GapInStream(tcptuple, tcp.TcpDirectionOriginal, 10, private) assert.Equal(t, false, drop) private = dns.ReceivedFin(tcptuple, tcp.TcpDirectionReverse, private) assert.Equal(t, 1, dns.transactions.Size(), "There should be one transaction.") client := dns.results.(publisher.ChanClient) close(client.Channel) mapStr := <-client.Channel assert.Nil(t, mapStr, "No result should have been published.") assert.Empty(t, mapStr["notes"], "There should be no notes") }
//this method is exclusive to RabbitMQ func TestAmqp_ExchangeUnbindTransaction(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendRequest = true data, err := hex.DecodeString("0100010000001c00280028000005746573743105" + "7465737432044d5346540000000000ce") assert.Nil(t, err) data2, err := hex.DecodeString("0100010000000400280033ce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) private = amqp.Parse(&req, tcptuple, 0, private) req = protos.Packet{Payload: data2} amqp.Parse(&req, tcptuple, 1, private) trans := expectTransaction(t, amqp) assert.Equal(t, "exchange.unbind", trans["method"]) assert.Equal(t, "exchange.unbind test2 test1", trans["request"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, common.OK_STATUS, trans["status"]) fields, ok := trans["amqp"].(common.MapStr) if !ok { t.Errorf("Field should be present") } assert.Equal(t, "test1", fields["destination"]) assert.Equal(t, "test2", fields["source"]) assert.Equal(t, "MSFT", fields["routing-key"]) assert.Equal(t, false, fields["no-wait"]) }
func TestAmqp_HideArguments(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.sendRequest = true amqp.parseHeaders = false amqp.parseArguments = false //parse args data, err := hex.DecodeString("0100010000004d0032000a00000a5465737448656164" + "6572180000003704626f6f6c74010362697462050568656c6c6f530000001f4869206461" + "726c696e6720c3aac3aac3aac3aac3aac3aac3aae697a5e69cacce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) private = amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, amqp) assert.Equal(t, "queue.declare", trans["method"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, "queue.declare TestHeader", trans["request"]) fields, ok := trans["amqp"].(common.MapStr) if !ok { t.Errorf("Field should be present") } assert.Equal(t, false, fields["durable"]) assert.Equal(t, true, fields["auto-delete"]) _, exists := fields["arguments"].(common.MapStr) if exists { t.Errorf("Arguments field should not be present") } //parse headers data, err = hex.DecodeString("01000100000013003c00280000000a546573744865616" + "4657200ce02000100000026003c0000000000000000001a98800a746578742f706c61696" + "e02060a656c206d656e73616a65ce0300010000001a54657374206865616465722066696" + "56c647320666f7265766572ce") assert.Nil(t, err) tcptuple = testTCPTuple() req = protos.Packet{Payload: data} private = protos.ProtocolData(new(amqpPrivateData)) amqp.Parse(&req, tcptuple, 0, private) trans = expectTransaction(t, amqp) assert.Equal(t, "basic.publish", trans["method"]) assert.Equal(t, "amqp", trans["type"]) fields, ok = trans["amqp"].(common.MapStr) if !ok { t.Errorf("Field should be present") } assert.Equal(t, "TestHeader", fields["routing-key"]) _, exists = fields["exchange"] assert.False(t, exists) assert.Equal(t, false, fields["mandatory"]) assert.Equal(t, false, fields["immediate"]) assert.Equal(t, nil, fields["message-id"]) assert.Equal(t, nil, fields["content-type"]) assert.Equal(t, nil, fields["delivery-mode"]) assert.Equal(t, nil, fields["priority"]) }
func TestAmqp_MaxBodyLength(t *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"amqp", "amqpdetailed"}) } amqp := amqpModForTests() amqp.maxBodyLength = 10 amqp.sendRequest = true data, err := hex.DecodeString("01000100000010003c002800000007546573744d617" + "800ce02000100000019003c0000000000000000001680000a746578742f706c61696ece" + "0300010000001649276d2061207665727920626967206d657373616765ce") assert.Nil(t, err) tcptuple := testTCPTuple() req := protos.Packet{Payload: data} private := protos.ProtocolData(new(amqpPrivateData)) //method frame private = amqp.Parse(&req, tcptuple, 0, private) trans := expectTransaction(t, amqp) assert.Equal(t, "basic.publish", trans["method"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, "I'm a very [...]", trans["request"]) assert.Equal(t, common.OK_STATUS, trans["status"]) fields, ok := trans["amqp"].(common.MapStr) if !ok { t.Errorf("Field should be present") } assert.Equal(t, "text/plain", fields["content-type"]) assert.Equal(t, "TestMax", fields["routing-key"]) assert.Equal(t, false, fields["immediate"]) assert.Equal(t, false, fields["mandatory"]) _, exists := fields["exchange"] assert.False(t, exists) data, err = hex.DecodeString("01000100000010003c002800000007546573744d6" + "17800ce02000100000018003c0000000000000000003a800009696d6167652f676966" + "ce0300010000003a41414141414141414141414141414141414141414141414141414141" + "414141414141414141414141414141414141414141414141414141414141ce") assert.Nil(t, err) tcptuple = testTCPTuple() req = protos.Packet{Payload: data} private = protos.ProtocolData(new(amqpPrivateData)) //method frame amqp.Parse(&req, tcptuple, 0, private) trans = expectTransaction(t, amqp) assert.Equal(t, "basic.publish", trans["method"]) assert.Equal(t, "amqp", trans["type"]) assert.Equal(t, "65 65 65 65 65 65 65 65 65 65 [...]", trans["request"]) assert.Equal(t, common.OK_STATUS, trans["status"]) fields, ok = trans["amqp"].(common.MapStr) if !ok { t.Errorf("Field should be present") } assert.Equal(t, "image/gif", fields["content-type"]) assert.Equal(t, "TestMax", fields["routing-key"]) assert.Equal(t, false, fields["immediate"]) assert.Equal(t, false, fields["mandatory"]) _, exists = fields["exchange"] assert.False(t, exists) }