func TestNewFromMethod(t *testing.T) { var method = &amqp.ExchangeDeclare{ Reserved1: 0, Exchange: "ex-method", Type: "topic", Passive: true, Durable: true, AutoDelete: true, Internal: true, NoWait: false, Arguments: amqp.NewTable(), } exMethod, err := NewFromMethod(method, true, make(chan *Exchange)) if err != nil { t.Errorf(err.Msg) } exNormal := NewExchange("ex-method", EX_TYPE_TOPIC, true, true, true, amqp.NewTable(), true, make(chan *Exchange)) if !exNormal.EquivalentExchanges(exMethod) { t.Errorf("Inconsistency between NewExchange and NewFromMethod") } // Bad exchange type method.Type = "headers" exMethod, err = NewFromMethod(method, true, make(chan *Exchange)) if err == nil { t.Errorf("Parsed bad exchange method") } if err.Code != 503 { t.Errorf("Wrong error code on bad exchange parse") } }
func (channel *Channel) startConnection() *amqp.AMQPError { // TODO(SHOULD): add fields: host, product, version, platform, copyright, information var capabilities = amqp.NewTable() capabilities.SetKey("publisher_confirms", false) capabilities.SetKey("basic.nack", true) var serverProps = amqp.NewTable() // TODO: the java rabbitmq client I'm using for load testing doesn't like these string // fields even though the go/python clients do. If they are set as longstr (bytes) // instead they work, so I'm doing that for now serverProps.SetKey("product", []byte("dispatchd")) serverProps.SetKey("version", []byte("0.1")) serverProps.SetKey("copyright", []byte("Jeffrey Jenkins, 2015")) serverProps.SetKey("capabilities", capabilities) serverProps.SetKey("platform", []byte(runtime.GOARCH)) host, err := os.Hostname() if err != nil { serverProps.SetKey("host", []byte("UnknownHostError")) } else { serverProps.SetKey("host", []byte(host)) } serverProps.SetKey("information", []byte("http://dispatchd.org")) channel.SendMethod(&amqp.ConnectionStart{0, 9, serverProps, []byte("PLAIN"), []byte("en_US")}) return nil }
func TestEquals(t *testing.T) { var bNil *Binding = nil b, _ := NewBinding("q1", "e1", "rk", amqp.NewTable(), false) same, _ := NewBinding("q1", "e1", "rk", amqp.NewTable(), false) diffQ, _ := NewBinding("DIFF", "e1", "rk", amqp.NewTable(), false) diffE, _ := NewBinding("q1", "DIFF", "rk", amqp.NewTable(), false) diffR, _ := NewBinding("q1", "e1", "DIFF", amqp.NewTable(), false) if b == nil || same == nil || diffQ == nil || diffE == nil || diffR == nil { t.Errorf("Failed to construct bindings") } if b.Equals(nil) || bNil.Equals(b) { t.Errorf("Comparison to nil was true!") } if !b.Equals(same) { t.Errorf("Equals returns false!") } if b.Equals(diffQ) { t.Errorf("Equals returns true on queue name diff!") } if b.Equals(diffE) { t.Errorf("Equals returns true on exchange name diff!") } if b.Equals(diffR) { t.Errorf("Equals returns true on routing key diff!") } }
func TestAddBinding(t *testing.T) { var ex = NewExchange("ex1", EX_TYPE_TOPIC, true, true, false, amqp.NewTable(), false, make(chan *Exchange)) ex.deleteActive = time.Now() // bad binding _, err := binding.NewBinding("q1", "ex1", "~!@", amqp.NewTable(), true) if err == nil { t.Errorf("No error with bad binding!") } if len(ex.bindings) != 0 { t.Errorf("Bad binding was added despite error") } // duplicate binding var b = bindingHelper("q1", "ex1", "a.b.c", true) err = ex.AddBinding(b, -1) if err != nil { t.Errorf(err.Error()) } if len(ex.bindings) != 1 { t.Errorf("Wrong number of bindings") } err = ex.AddBinding(b, -1) if err != nil { t.Errorf(err.Error()) } if len(ex.bindings) != 1 { t.Errorf("Wrong number of bindings") } if ex.deleteActive != time.Unix(0, 0) { t.Errorf("Error did not reset time") } }
func TestTopicRouting(t *testing.T) { _, err := NewBinding("q1", "e1", "(", amqp.NewTable(), true) if err == nil { t.Errorf("Bad topic patter compiled!") } basic, _ := NewBinding("q1", "e1", "hello.world", amqp.NewTable(), true) singleWild, _ := NewBinding("q1", "e1", "hello.*.world", amqp.NewTable(), true) multiWild, _ := NewBinding("q1", "e1", "hello.#.world", amqp.NewTable(), true) multiWild2, _ := NewBinding("q1", "e1", "hello.#.world.#", amqp.NewTable(), true) if !basic.MatchTopic(basicPublish("e1", "hello.world")) { t.Errorf("Basic match failed") } if basic.MatchTopic(basicPublish("e1", "hello.worlds")) { t.Errorf("Incorrect match with suffix") } if !basic.MatchTopic(basicPublish("e1", "hello.world")) { t.Errorf("Match succeeded despite mismatched exchange") } if !singleWild.MatchTopic(basicPublish("e1", "hello.one.world")) { t.Errorf("Failed to match single wildcard") } if singleWild.MatchTopic(basicPublish("e1", "hello.world")) { t.Errorf("Matched without wildcard token") } if !multiWild.MatchTopic(basicPublish("e1", "hello.one.two.three.world")) { t.Errorf("Failed to match multi wildcard") } if !multiWild2.MatchTopic(basicPublish("e1", "hello.one.world.hi")) { t.Errorf("Multiple multi-wild tokens failed") } }
func TestAutoDeleteTimeout(t *testing.T) { var deleter = make(chan *Exchange) var ex = NewExchange("ex1", EX_TYPE_TOPIC, true, true, false, amqp.NewTable(), false, deleter) ex.autodeletePeriod = 10 * time.Millisecond ex.AddBinding(bindingHelper("q1", "ex1", "a.b.c", true), -1) var b, _ = binding.NewBinding("q1", "ex1", "a.b.c", amqp.NewTable(), true) ex.RemoveBinding(b) var toDelete = <-deleter if ex.Name != toDelete.Name { t.Errorf("Integrity error in delete") } }
func TestExchangeRoutingFanout(t *testing.T) { var exFanout = NewExchange( "exf", EX_TYPE_FANOUT, false, false, false, amqp.NewTable(), false, make(chan *Exchange), ) exFanout.AddBinding(bindingHelper("q1", "exf", "rk-1", false), -1) exFanout.AddBinding(bindingHelper("q2", "exf", "rk-2", false), -1) // Create a random message, won't route by default var msg = amqp.RandomMessage(false) msg.Method.Exchange = "exf" res, err := exFanout.QueuesForPublish(msg) if err != nil { t.Errorf(err.Msg) } _, foundQ1 := res["q1"] _, foundQ2 := res["q2"] if !foundQ1 || !foundQ2 { t.Errorf("Failed to route fanout message %v %v", foundQ1, foundQ2) } }
func bindingHelper(queue string, exchange string, key string, topic bool) *binding.Binding { b, err := binding.NewBinding(queue, exchange, key, amqp.NewTable(), topic) if err != nil { panic(err.Error()) } return b }
func TestRemoveBinding(t *testing.T) { var ex = NewExchange("ex1", EX_TYPE_TOPIC, true, true, false, amqp.NewTable(), false, make(chan *Exchange)) var b1 = bindingHelper("q1", "ex1", "a.b.c", true) var b2 = bindingHelper("q1", "ex1", "d.e.f", true) var b3 = bindingHelper("q1", "ex1", "g.h.i", true) var b4 = bindingHelper("q2", "ex1", "g.h.i", true) var b5 = bindingHelper("q2", "ex1", "j.k.l", true) // ex.AddBinding(b1, -1) ex.AddBinding(b2, -1) ex.AddBinding(b3, -1) ex.AddBinding(b4, -1) ex.AddBinding(b5, -1) // Remove a binding that doesn't exist bNone := bindingHelper("q2", "ex1", "does.not.exist", true) ex.RemoveBinding(bNone) if len(ex.bindings) != 5 { t.Errorf("Wrong number of bindings: %d", len(ex.bindings)) } // Remove the Q2 bindings ex.RemoveBinding(b4) if len(ex.bindings) != 4 { t.Errorf("Wrong number of bindings: %d", len(ex.bindings)) } ex.RemoveBinding(b5) // Check that all q2 bindings are gone if len(ex.BindingsForQueue("q2")) != 0 { t.Errorf("Wrong number of bindings") } }
func TestRemoveBindingsForQueue(t *testing.T) { var ex = NewExchange("ex1", EX_TYPE_TOPIC, true, true, false, amqp.NewTable(), false, make(chan *Exchange)) var b1 = bindingHelper("q1", "ex1", "a.b.c", true) var b2 = bindingHelper("q1", "ex1", "d.e.f", true) var b3 = bindingHelper("q1", "ex1", "g.h.i", true) var b4 = bindingHelper("q2", "ex1", "g.h.i", true) var b5 = bindingHelper("q2", "ex1", "j.k.l", true) // ex.AddBinding(b1, -1) ex.AddBinding(b2, -1) ex.AddBinding(b3, -1) ex.AddBinding(b4, -1) ex.AddBinding(b5, -1) ex.RemoveBindingsForQueue("q0") if len(ex.bindings) != 5 { t.Errorf("Wrong number of bindings after removing q0 bindings") } ex.RemoveBindingsForQueue("q1") if len(ex.bindings) != 2 { t.Errorf("Wrong number of bindings after removing q1 bindings") } ex.RemoveBindingsForQueue("q2") if len(ex.bindings) != 0 { t.Errorf("Wrong number of bindings after removing q2 bindings: %v", ex.bindings) } }
func TestFanout(t *testing.T) { b, _ := NewBinding("q1", "e1", "rk", amqp.NewTable(), false) if b.MatchFanout(basicPublish("DIFF", "asdf")) { t.Errorf("Fanout did not check exchanges") } if !b.MatchFanout(basicPublish("e1", "asdf")) { t.Errorf("Fanout didn't match regardless of key") } }
func TestDirect(t *testing.T) { b, _ := NewBinding("q1", "e1", "rk", amqp.NewTable(), false) if b.MatchDirect(basicPublish("DIFF", "asdf")) { t.Errorf("MatchDirect did not check exchanges") } if b.MatchDirect(basicPublish("e1", "asdf")) { t.Errorf("MatchDirect matched even with the wrong key") } if !b.MatchDirect(basicPublish("e1", "rk")) { t.Errorf("MatchDirect did not match with the correct key and exchange") } }
func TestExchangeRoutingTopic(t *testing.T) { var exTopic = NewExchange( "ext", EX_TYPE_TOPIC, false, false, false, amqp.NewTable(), false, make(chan *Exchange), ) exTopic.AddBinding(bindingHelper("q1", "ext", "api.msg.*.json", true), -1) exTopic.AddBinding(bindingHelper("q1", "ext", "api.*.home.json", true), -1) exTopic.AddBinding(bindingHelper("q2", "ext", "api.msg.home.json", true), -1) exTopic.AddBinding(bindingHelper("q3", "ext", "log.#", true), -1) // Create a random message, won't route by default var msg = amqp.RandomMessage(false) msg.Method.Exchange = "ext" // no match res, err := exTopic.QueuesForPublish(msg) if err != nil { t.Errorf(err.Msg) } if len(res) > 0 { t.Errorf("Routed message which should not have routed", res) } // one match on # msg.Method.RoutingKey = "log.msg.home.json" res, err = exTopic.QueuesForPublish(msg) if err != nil { t.Errorf(err.Msg) } _, foundLog := res["q3"] if !foundLog || len(res) != 1 { t.Errorf("Bad results routing to # key") } // one queue on two matches msg.Method.RoutingKey = "api.msg.home.json" res, err = exTopic.QueuesForPublish(msg) if err != nil { t.Errorf(err.Msg) } _, foundQ1 := res["q1"] _, foundQ2 := res["q2"] if !foundQ1 || !foundQ2 || len(res) != 2 { t.Errorf("Bad results routing to multiply-bound * key") } }
func exchangeForTest(name string, typ uint8) *Exchange { return NewExchange( name, typ, false, false, false, amqp.NewTable(), false, make(chan *Exchange), ) }
func (server *Server) addQueue(q *queue.Queue) error { server.serverLock.Lock() defer server.serverLock.Unlock() server.queues[q.Name] = q var defaultExchange = server.exchanges[""] var defaultBinding, err = binding.NewBinding(q.Name, "", q.Name, amqp.NewTable(), false) if err != nil { return err } defaultExchange.AddBinding(defaultBinding, q.ConnId) q.Start() return nil }
func TestExchangeRoutingDirect(t *testing.T) { // Make exchange ang binding var exDirect = NewExchange( "exd", EX_TYPE_DIRECT, false, false, false, amqp.NewTable(), false, make(chan *Exchange), ) exDirect.AddBinding(bindingHelper("q1", "exd", "rk-1", false), -1) // Create a random message, won't route by default var msg = amqp.RandomMessage(false) // Test wrong exchange for coverage res, err := exDirect.QueuesForPublish(msg) if err != nil { t.Errorf(err.Msg) } if len(res) > 0 { t.Errorf("Routed message which should not have routed", res) } // Test right exchange, wrong key msg.Method.Exchange = "exd" res, err = exDirect.QueuesForPublish(msg) if err != nil { t.Errorf(err.Msg) } if len(res) > 0 { t.Errorf("Routed message which should not have routed", res) } // Set the right values for routing msg.Method.RoutingKey = "rk-1" res, err = exDirect.QueuesForPublish(msg) if err != nil { t.Errorf(err.Msg) } if _, found := res["q1"]; !found { t.Errorf("Failed to route direct message: %s", res) } }
func TestPersistence(t *testing.T) { var dbFile = "TestBindingPersistence.db" os.Remove(dbFile) defer os.Remove(dbFile) db, err := bolt.Open(dbFile, 0600, nil) if err != nil { t.Errorf("Failed to create db") } // Persist b, err := NewBinding("q1", "ex1", "rk1", amqp.NewTable(), true) if err != nil { t.Errorf("Error in NewBinding") } err = b.Persist(db) if err != nil { t.Errorf("Error in NewBinding") } // Read bMap, err := LoadAllBindings(db) if err != nil { t.Errorf("Error in LoadAllBindings") } if len(bMap) != 1 { t.Errorf("Wrong number of bindings") } for _, b2 := range bMap { if !b2.Equals(b) { t.Errorf("Did not get the same binding from the db") } } // Depersist b.Depersist(db) bMap, err = LoadAllBindings(db) if err != nil { t.Errorf("Error in LoadAllBindings") } if len(bMap) != 0 { t.Errorf("Wrong number of bindings") } }
func TestPersistence(t *testing.T) { // Create DB var dbFile = "TestExchangePersistence.db" os.Remove(dbFile) defer os.Remove(dbFile) db, err := bolt.Open(dbFile, 0600, nil) if err != nil { t.Errorf("Failed to create db") } var ex = exchangeForTest("ex1", EX_TYPE_TOPIC) ex.Durable = true err = ex.Persist(db) if err != nil { t.Errorf("Could not persist exchange %s", ex.Name) } ex.Name = "" err = ex.Persist(db) if err != nil { t.Errorf(err.Error()) } // Read deleteChan := make(chan *Exchange) _, err = NewFromDisk(db, "ex1", deleteChan) if err != nil { t.Errorf("Error loading persisted exchage %s", err.Error()) } _, err = NewFromDisk(db, "", deleteChan) if err != nil { t.Errorf("Error loading persisted exchage %s", err.Error()) } // Depersist realEx := NewExchange("ex1", EX_TYPE_TOPIC, true, false, false, amqp.NewTable(), false, make(chan *Exchange)) realEx.AddBinding(bindingHelper("q1", "ex1", "api.msg.*.json", true), -1) realEx.Depersist(db) // Verify _, err = NewFromDisk(db, "ex1", deleteChan) if err == nil { t.Errorf("Failed to delete exchange 'ex1'") } }
func TestJson(t *testing.T) { basic, _ := NewBinding("q1", "e1", "hello.world", amqp.NewTable(), true) var basicBytes, err = basic.MarshalJSON() if err != nil { t.Errorf(err.Error()) } expectedBytes, err := json.Marshal(map[string]interface{}{ "queueName": "q1", "exchangeName": "e1", "key": "hello.world", "arguments": make(map[string]interface{}), }) if string(expectedBytes) != string(basicBytes) { t.Logf("Expected: %s", expectedBytes) t.Logf("Got: %s", basicBytes) t.Errorf("Wrong json bytes!") } }
func (server *Server) genDefaultExchange(name string, typ uint8) { _, hasKey := server.exchanges[name] if !hasKey { var ex = exchange.NewExchange( name, exchange.EX_TYPE_TOPIC, true, false, false, amqp.NewTable(), true, server.exchangeDeleter, ) // Persist ex.Persist(server.db) err := server.addExchange(ex) if err != nil { panic(err.Error()) } } }
func TestBindingsForQueue(t *testing.T) { var ex = NewExchange("ex1", EX_TYPE_TOPIC, true, true, false, amqp.NewTable(), false, make(chan *Exchange)) var b1 = bindingHelper("q1", "ex1", "a.b.c", true) var b2 = bindingHelper("q1", "ex1", "d.e.f", true) var b3 = bindingHelper("q1", "ex1", "g.h.i", true) var b4 = bindingHelper("q2", "ex1", "g.h.i", true) var b5 = bindingHelper("q2", "ex1", "j.k.l", true) // ex.AddBinding(b1, -1) ex.AddBinding(b2, -1) ex.AddBinding(b3, -1) ex.AddBinding(b4, -1) ex.AddBinding(b5, -1) if len(ex.BindingsForQueue("q1")) != 3 { t.Errorf("Wrong number of bindings for q1") } if len(ex.BindingsForQueue("q2")) != 2 { t.Errorf("Wrong number of bindings for q2") } if len(ex.BindingsForQueue("q0")) != 0 { t.Errorf("Wrong number of bindings for q0") } }
func TestEquivalentExchanges(t *testing.T) { var ex = NewExchange( "ex1", EX_TYPE_DIRECT, true, true, true, amqp.NewTable(), true, make(chan *Exchange), ) var ex2 = NewExchange( "ex1", EX_TYPE_DIRECT, true, true, true, amqp.NewTable(), true, make(chan *Exchange), ) // Same if !ex.EquivalentExchanges(ex2) { t.Errorf("Same exchanges aren't equal!") } // name ex2.Name = "ex2" if ex.EquivalentExchanges(ex2) { t.Errorf("Different exchanges are equal!") } ex2.Name = "ex1" // extype ex2.ExType = EX_TYPE_TOPIC if ex.EquivalentExchanges(ex2) { t.Errorf("Different exchanges are equal!") } ex2.ExType = EX_TYPE_DIRECT // internal ex2.Internal = false if ex.EquivalentExchanges(ex2) { t.Errorf("Different exchanges are equal!") } ex2.Internal = true // durable ex2.Durable = false if ex.EquivalentExchanges(ex2) { t.Errorf("Different exchanges are equal!") } ex2.Durable = true // args var newTable = amqp.NewTable() newTable.SetKey("stuff", true) ex2.Arguments = newTable if ex.EquivalentExchanges(ex2) { t.Errorf("Different exchanges are equal!") } ex2.Arguments = amqp.NewTable() // test other diffs ok ex2.System = false ex2.AutoDelete = false if !ex.EquivalentExchanges(ex2) { t.Errorf("Same exchanges aren't equal!") } }