From 1fd87211197b929da9f307d26c5969f2e94dd2f6 Mon Sep 17 00:00:00 2001
From: Benjamin Wenger <ben@elixxir.ioo>
Date: Mon, 29 Aug 2022 16:38:16 -0700
Subject: [PATCH] finished tested the event model

---
 channels/eventModel.go      |   2 +-
 channels/eventModel_test.go | 754 ++++++++++++++++++++++++++++++++++++
 channels/messages.go        |  23 +-
 channels/messages_test.go   |  97 ++---
 channels/userListener.go    |   2 +-
 5 files changed, 799 insertions(+), 79 deletions(-)
 create mode 100644 channels/eventModel_test.go

diff --git a/channels/eventModel.go b/channels/eventModel.go
index f3c805b08..332ab75ba 100644
--- a/channels/eventModel.go
+++ b/channels/eventModel.go
@@ -116,7 +116,7 @@ func (e *events) RegisterReceiveHandler(messageType MessageType,
 // triggerEvent is an internal function which is used to trigger message
 // reception on a message received from a user (symmetric encryption)
 // It will call the appropriate MessageTypeHandler assuming one exists.
-func (e *events) triggerEvent(chID *id.ID, umi *UserMessageInternal,
+func (e *events) triggerEvent(chID *id.ID, umi *userMessageInternal,
 	receptionID receptionID.EphemeralIdentity, round rounds.Round) {
 	um := umi.GetUserMessage()
 	cm := umi.GetChannelMessage()
diff --git a/channels/eventModel_test.go b/channels/eventModel_test.go
new file mode 100644
index 000000000..e6d4cb579
--- /dev/null
+++ b/channels/eventModel_test.go
@@ -0,0 +1,754 @@
+package channels
+
+import (
+	"bytes"
+	"github.com/golang/protobuf/proto"
+	"gitlab.com/elixxir/client/cmix/identity/receptionID"
+	"gitlab.com/elixxir/client/cmix/rounds"
+	cryptoBroadcast "gitlab.com/elixxir/crypto/broadcast"
+	cryptoChannel "gitlab.com/elixxir/crypto/channel"
+	"gitlab.com/elixxir/primitives/states"
+	"gitlab.com/xx_network/primitives/id"
+	"reflect"
+	"runtime"
+	"testing"
+	"time"
+)
+
+type eventReceive struct {
+	channelID      *id.ID
+	messageID      cryptoChannel.MessageID
+	reactionTo     cryptoChannel.MessageID
+	senderUsername string
+	content        []byte
+	timestamp      time.Time
+	lease          time.Duration
+	round          rounds.Round
+}
+
+type MockEvent struct {
+	eventReceive
+}
+
+func (*MockEvent) JoinChannel(channel cryptoBroadcast.Channel) {}
+func (*MockEvent) LeaveChannel(channelID *id.ID)               {}
+func (m *MockEvent) ReceiveMessage(channelID *id.ID, messageID cryptoChannel.MessageID,
+	senderUsername string, text string,
+	timestamp time.Time, lease time.Duration, round rounds.Round) {
+	m.eventReceive = eventReceive{
+		channelID:      channelID,
+		messageID:      messageID,
+		reactionTo:     cryptoChannel.MessageID{},
+		senderUsername: senderUsername,
+		content:        []byte(text),
+		timestamp:      timestamp,
+		lease:          lease,
+		round:          round,
+	}
+}
+func (m *MockEvent) ReceiveReply(channelID *id.ID, messageID cryptoChannel.MessageID,
+	replyTo cryptoChannel.MessageID, senderUsername string,
+	text string, timestamp time.Time, lease time.Duration,
+	round rounds.Round) {
+	m.eventReceive = eventReceive{
+		channelID:      channelID,
+		messageID:      messageID,
+		reactionTo:     replyTo,
+		senderUsername: senderUsername,
+		content:        []byte(text),
+		timestamp:      timestamp,
+		lease:          lease,
+		round:          round,
+	}
+}
+func (m *MockEvent) ReceiveReaction(channelID *id.ID, messageID cryptoChannel.MessageID,
+	reactionTo cryptoChannel.MessageID, senderUsername string,
+	reaction string, timestamp time.Time, lease time.Duration,
+	round rounds.Round) {
+	m.eventReceive = eventReceive{
+		channelID:      channelID,
+		messageID:      messageID,
+		reactionTo:     reactionTo,
+		senderUsername: senderUsername,
+		content:        []byte(reaction),
+		timestamp:      timestamp,
+		lease:          lease,
+		round:          round,
+	}
+}
+
+func Test_initEvents(t *testing.T) {
+
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	// verify the model is registered
+	if e.model != me {
+		t.Errorf("Event model is not registered")
+	}
+
+	// check registered channels was created
+	if e.registered == nil {
+		t.Fatalf("Registered handlers is not registered")
+	}
+
+	// check that all the default callbacks are registered
+	if len(e.registered) != 3 {
+		t.Errorf("The correct number of default handlers are not "+
+			"registered; %d vs %d", len(e.registered), 3)
+		//If this fails, is means the default handlers have changed. edit the
+		//number here and add tests below. be suspicious if it goes down.
+	}
+
+	if getFuncName(e.registered[Text]) != getFuncName(e.receiveTextMessage) {
+		t.Errorf("Text does not have recieveTextMessageRegistred")
+	}
+
+	if getFuncName(e.registered[AdminText]) != getFuncName(e.receiveTextMessage) {
+		t.Errorf("AdminText does not have recieveTextMessageRegistred")
+	}
+
+	if getFuncName(e.registered[Reaction]) != getFuncName(e.receiveReaction) {
+		t.Errorf("Reaction does not have recieveReaction")
+	}
+}
+
+func TestEvents_RegisterReceiveHandler(t *testing.T) {
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	//test that a new receive handler can be registered.
+	mt := MessageType(42)
+	err := e.RegisterReceiveHandler(mt, e.receiveReaction)
+	if err != nil {
+		t.Fatalf("Failed to register '%s' when it should be "+
+			"sucesfull: %+v", mt, err)
+	}
+
+	//check that it is written
+	returnedHandler, exists := e.registered[mt]
+	if !exists {
+		t.Fatalf("Failed to get handler '%s' after registration", mt)
+	}
+
+	//check that the correct function is written
+	if getFuncName(e.receiveReaction) != getFuncName(returnedHandler) {
+		t.Fatalf("Failed to get correct handler for '%s' after "+
+			"registration, %s vs %s", mt, getFuncName(e.receiveReaction),
+			getFuncName(returnedHandler))
+	}
+
+	//test that writing to the same receive handler fails
+	err = e.RegisterReceiveHandler(mt, e.receiveTextMessage)
+	if err == nil {
+		t.Fatalf("Failed to register '%s' when it should be "+
+			"sucesfull: %+v", mt, err)
+	} else if err != MessageTypeAlreadyRegistered {
+		t.Fatalf("Wrong error returned when reregierting message "+
+			"tyle '%s': %+v", mt, err)
+	}
+
+	//check that it is still written
+	returnedHandler, exists = e.registered[mt]
+	if !exists {
+		t.Fatalf("Failed to get handler '%s' after second "+
+			"registration", mt)
+	}
+
+	//check that the correct function is written
+	if getFuncName(e.receiveReaction) != getFuncName(returnedHandler) {
+		t.Fatalf("Failed to get correct handler for '%s' after "+
+			"second registration, %s vs %s", mt, getFuncName(e.receiveReaction),
+			getFuncName(returnedHandler))
+	}
+}
+
+type dummyMessageTypeHandler struct {
+	channelID      *id.ID
+	messageID      cryptoChannel.MessageID
+	messageType    MessageType
+	senderUsername string
+	content        []byte
+	timestamp      time.Time
+	lease          time.Duration
+	round          rounds.Round
+}
+
+func (dmth *dummyMessageTypeHandler) dummyMessageTypeReceiveMessage(
+	channelID *id.ID, messageID cryptoChannel.MessageID,
+	messageType MessageType, senderUsername string, content []byte,
+	timestamp time.Time, lease time.Duration, round rounds.Round) {
+	dmth.channelID = channelID
+	dmth.messageID = messageID
+	dmth.messageType = messageType
+	dmth.senderUsername = senderUsername
+	dmth.content = content
+	dmth.timestamp = timestamp
+	dmth.lease = lease
+	dmth.round = round
+}
+
+func TestEvents_triggerEvents(t *testing.T) {
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	dummy := &dummyMessageTypeHandler{}
+
+	//register the handler
+	mt := MessageType(42)
+	err := e.RegisterReceiveHandler(mt, dummy.dummyMessageTypeReceiveMessage)
+	if err != nil {
+		t.Fatalf("Error on registration, should not have happened: "+
+			"%+v", err)
+	}
+
+	//craft the input for the event
+	chID := &id.ID{}
+	chID[0] = 1
+
+	umi, _, _ := builtTestUMI(t, mt)
+
+	r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)}
+	r.Timestamps[states.QUEUED] = time.Now()
+
+	//call the trigger
+	e.triggerEvent(chID, umi, receptionID.EphemeralIdentity{}, r)
+
+	//check the data is stored in the dummy
+	if !dummy.channelID.Cmp(chID) {
+		t.Errorf("The channel IDs do not match %s vs %s",
+			dummy.channelID, chID)
+	}
+
+	if !dummy.messageID.Equals(umi.GetMessageID()) {
+		t.Errorf("The message IDs do not match %s vs %s",
+			dummy.messageID, umi.GetMessageID())
+	}
+
+	if dummy.messageType != mt {
+		t.Errorf("The message types do not match %s vs %s",
+			dummy.messageType, mt)
+	}
+
+	if dummy.senderUsername != umi.GetUserMessage().Username {
+		t.Errorf("The usernames do not match %s vs %s",
+			dummy.senderUsername, umi.GetUserMessage().Username)
+	}
+
+	if !bytes.Equal(dummy.content, umi.GetChannelMessage().Payload) {
+		t.Errorf("The payloads do not match %s vs %s",
+			dummy.content, umi.GetChannelMessage().Payload)
+	}
+
+	if !dummy.timestamp.Equal(r.Timestamps[states.QUEUED]) {
+		t.Errorf("The timestamps do not match %s vs %s",
+			dummy.timestamp, r.Timestamps[states.QUEUED])
+	}
+
+	if dummy.lease != time.Duration(umi.GetChannelMessage().Lease) {
+		t.Errorf("The messge lease durations do not match %s vs %s",
+			dummy.lease, time.Duration(umi.GetChannelMessage().Lease))
+	}
+
+	if dummy.round.ID != r.ID {
+		t.Errorf("The messge round does not match %s vs %s",
+			dummy.round.ID, r.ID)
+	}
+}
+
+func TestEvents_triggerAdminEvents(t *testing.T) {
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	dummy := &dummyMessageTypeHandler{}
+
+	//register the handler
+	mt := MessageType(42)
+	err := e.RegisterReceiveHandler(mt, dummy.dummyMessageTypeReceiveMessage)
+	if err != nil {
+		t.Fatalf("Error on registration, should not have happened: "+
+			"%+v", err)
+	}
+
+	//craft the input for the event
+	chID := &id.ID{}
+	chID[0] = 1
+
+	u, _, cm := builtTestUMI(t, mt)
+
+	r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)}
+	r.Timestamps[states.QUEUED] = time.Now()
+
+	msgID := cryptoChannel.MakeMessageID(u.userMessage.Message)
+
+	//call the trigger
+	e.triggerAdminEvent(chID, cm, msgID, receptionID.EphemeralIdentity{}, r)
+
+	//check the data is stored in the dummy
+	if !dummy.channelID.Cmp(chID) {
+		t.Errorf("The channel IDs do not match %s vs %s",
+			dummy.channelID, chID)
+	}
+
+	if !dummy.messageID.Equals(msgID) {
+		t.Errorf("The message IDs do not match %s vs %s",
+			dummy.messageID, msgID)
+	}
+
+	if dummy.messageType != mt {
+		t.Errorf("The message types do not match %s vs %s",
+			dummy.messageType, mt)
+	}
+
+	if dummy.senderUsername != AdminUsername {
+		t.Errorf("The usernames do not match %s vs %s",
+			dummy.senderUsername, AdminUsername)
+	}
+
+	if !bytes.Equal(dummy.content, cm.Payload) {
+		t.Errorf("The payloads do not match %s vs %s",
+			dummy.senderUsername, cm.Payload)
+	}
+
+	if !dummy.timestamp.Equal(r.Timestamps[states.QUEUED]) {
+		t.Errorf("The timestamps do not match %s vs %s",
+			dummy.timestamp, r.Timestamps[states.QUEUED])
+	}
+
+	if dummy.lease != time.Duration(cm.Lease) {
+		t.Errorf("The messge lease durations do not match %s vs %s",
+			dummy.lease, time.Duration(cm.Lease))
+	}
+
+	if dummy.round.ID != r.ID {
+		t.Errorf("The messge round does not match %s vs %s",
+			dummy.round.ID, r.ID)
+	}
+}
+
+func TestEvents_receiveTextMessage_Message(t *testing.T) {
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	//craft the input for the event
+	chID := &id.ID{}
+	chID[0] = 1
+
+	textPayload := &CMIXChannelText{
+		Version:        0,
+		Text:           "They Don't Think It Be Like It Is, But It Do",
+		ReplyMessageID: nil,
+	}
+
+	textMarshaled, err := proto.Marshal(textPayload)
+	if err != nil {
+		t.Fatalf("failed to marshael the message proto: %+v", err)
+	}
+
+	msgID := cryptoChannel.MakeMessageID(textMarshaled)
+
+	senderUsername := "Alice"
+	ts := time.Now()
+
+	lease := 69 * time.Minute
+
+	r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)}
+	r.Timestamps[states.QUEUED] = time.Now()
+
+	//call the handler
+	e.receiveTextMessage(chID, msgID, 0, senderUsername,
+		textMarshaled, ts, lease, r)
+
+	//check the results on the model
+	if !me.eventReceive.channelID.Cmp(chID) {
+		t.Errorf("Channel ID did not propogate correctly, %s vs %s",
+			me.eventReceive.channelID, chID)
+	}
+
+	if !me.eventReceive.messageID.Equals(msgID) {
+		t.Errorf("Message ID did not propogate correctly, %s vs %s",
+			me.eventReceive.messageID, msgID)
+	}
+
+	if !me.eventReceive.reactionTo.Equals(cryptoChannel.MessageID{}) {
+		t.Errorf("Reaction ID is not blank, %s",
+			me.eventReceive.reactionTo)
+	}
+
+	if me.eventReceive.senderUsername != senderUsername {
+		t.Errorf("SenderID propogate correctly, %s vs %s",
+			me.eventReceive.senderUsername, senderUsername)
+	}
+
+	if me.eventReceive.timestamp != ts {
+		t.Errorf("Message timestamp did not propogate correctly, %s vs %s",
+			me.eventReceive.timestamp, ts)
+	}
+
+	if me.eventReceive.lease != lease {
+		t.Errorf("Message lease did not propogate correctly, %s vs %s",
+			me.eventReceive.lease, lease)
+	}
+
+	if me.eventReceive.round.ID != r.ID {
+		t.Errorf("Message round did not propogate correctly, %d vs %d",
+			me.eventReceive.round.ID, r.ID)
+	}
+}
+
+func TestEvents_receiveTextMessage_Reply(t *testing.T) {
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	//craft the input for the event
+	chID := &id.ID{}
+	chID[0] = 1
+
+	replyMsgId := cryptoChannel.MakeMessageID([]byte("blarg"))
+
+	textPayload := &CMIXChannelText{
+		Version:        0,
+		Text:           "They Don't Think It Be Like It Is, But It Do",
+		ReplyMessageID: replyMsgId[:],
+	}
+
+	textMarshaled, err := proto.Marshal(textPayload)
+	if err != nil {
+		t.Fatalf("failed to marshael the message proto: %+v", err)
+	}
+
+	msgID := cryptoChannel.MakeMessageID(textMarshaled)
+
+	senderUsername := "Alice"
+	ts := time.Now()
+
+	lease := 69 * time.Minute
+
+	r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)}
+	r.Timestamps[states.QUEUED] = time.Now()
+
+	//call the handler
+	e.receiveTextMessage(chID, msgID, 0, senderUsername,
+		textMarshaled, ts, lease, r)
+
+	//check the results on the model
+	if !me.eventReceive.channelID.Cmp(chID) {
+		t.Errorf("Channel ID did not propogate correctly, %s vs %s",
+			me.eventReceive.channelID, chID)
+	}
+
+	if !me.eventReceive.messageID.Equals(msgID) {
+		t.Errorf("Message ID did not propogate correctly, %s vs %s",
+			me.eventReceive.messageID, msgID)
+	}
+
+	if !me.eventReceive.reactionTo.Equals(replyMsgId) {
+		t.Errorf("Reaction ID is not equal to what was passed in, "+
+			"%s vs %s", me.eventReceive.reactionTo, replyMsgId)
+	}
+
+	if me.eventReceive.senderUsername != senderUsername {
+		t.Errorf("SenderID propogate correctly, %s vs %s",
+			me.eventReceive.senderUsername, senderUsername)
+	}
+
+	if me.eventReceive.timestamp != ts {
+		t.Errorf("Message timestamp did not propogate correctly, "+
+			"%s vs %s", me.eventReceive.timestamp, ts)
+	}
+
+	if me.eventReceive.lease != lease {
+		t.Errorf("Message lease did not propogate correctly, %s vs %s",
+			me.eventReceive.lease, lease)
+	}
+
+	if me.eventReceive.round.ID != r.ID {
+		t.Errorf("Message round did not propogate correctly, %d vs %d",
+			me.eventReceive.round.ID, r.ID)
+	}
+}
+
+func TestEvents_receiveTextMessage_Reply_BadReply(t *testing.T) {
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	//craft the input for the event
+	chID := &id.ID{}
+	chID[0] = 1
+
+	replyMsgId := []byte("blarg")
+
+	textPayload := &CMIXChannelText{
+		Version:        0,
+		Text:           "They Don't Think It Be Like It Is, But It Do",
+		ReplyMessageID: replyMsgId[:],
+	}
+
+	textMarshaled, err := proto.Marshal(textPayload)
+	if err != nil {
+		t.Fatalf("failed to marshael the message proto: %+v", err)
+	}
+
+	msgID := cryptoChannel.MakeMessageID(textMarshaled)
+
+	senderUsername := "Alice"
+	ts := time.Now()
+
+	lease := 69 * time.Minute
+
+	r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)}
+	r.Timestamps[states.QUEUED] = time.Now()
+
+	//call the handler
+	e.receiveTextMessage(chID, msgID, 0, senderUsername,
+		textMarshaled, ts, lease, r)
+
+	//check the results on the model
+	if !me.eventReceive.channelID.Cmp(chID) {
+		t.Errorf("Channel ID did not propogate correctly, %s vs %s",
+			me.eventReceive.channelID, chID)
+	}
+
+	if !me.eventReceive.messageID.Equals(msgID) {
+		t.Errorf("Message ID did not propogate correctly, %s vs %s",
+			me.eventReceive.messageID, msgID)
+	}
+
+	if !me.eventReceive.reactionTo.Equals(cryptoChannel.MessageID{}) {
+		t.Errorf("Reaction ID is not blank, %s",
+			me.eventReceive.reactionTo)
+	}
+
+	if me.eventReceive.senderUsername != senderUsername {
+		t.Errorf("SenderID propogate correctly, %s vs %s",
+			me.eventReceive.senderUsername, senderUsername)
+	}
+
+	if me.eventReceive.timestamp != ts {
+		t.Errorf("Message timestamp did not propogate correctly, "+
+			"%s vs %s", me.eventReceive.timestamp, ts)
+	}
+
+	if me.eventReceive.lease != lease {
+		t.Errorf("Message lease did not propogate correctly, %s vs %s",
+			me.eventReceive.lease, lease)
+	}
+
+	if me.eventReceive.round.ID != r.ID {
+		t.Errorf("Message round did not propogate correctly, %d vs %d",
+			me.eventReceive.round.ID, r.ID)
+	}
+}
+
+func TestEvents_receiveReaction(t *testing.T) {
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	//craft the input for the event
+	chID := &id.ID{}
+	chID[0] = 1
+
+	replyMsgId := cryptoChannel.MakeMessageID([]byte("blarg"))
+
+	textPayload := &CMIXChannelReaction{
+		Version:           0,
+		Reaction:          "🍆",
+		ReactionMessageID: replyMsgId[:],
+	}
+
+	textMarshaled, err := proto.Marshal(textPayload)
+	if err != nil {
+		t.Fatalf("failed to marshael the message proto: %+v", err)
+	}
+
+	msgID := cryptoChannel.MakeMessageID(textMarshaled)
+
+	senderUsername := "Alice"
+	ts := time.Now()
+
+	lease := 69 * time.Minute
+
+	r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)}
+	r.Timestamps[states.QUEUED] = time.Now()
+
+	//call the handler
+	e.receiveReaction(chID, msgID, 0, senderUsername,
+		textMarshaled, ts, lease, r)
+
+	//check the results on the model
+	if !me.eventReceive.channelID.Cmp(chID) {
+		t.Errorf("Channel ID did not propogate correctly, %s vs %s",
+			me.eventReceive.channelID, chID)
+	}
+
+	if !me.eventReceive.messageID.Equals(msgID) {
+		t.Errorf("Message ID did not propogate correctly, %s vs %s",
+			me.eventReceive.messageID, msgID)
+	}
+
+	if !me.eventReceive.reactionTo.Equals(replyMsgId) {
+		t.Errorf("Reaction ID is not equal to what was passed in, "+
+			"%s vs %s", me.eventReceive.reactionTo, replyMsgId)
+	}
+
+	if me.eventReceive.senderUsername != senderUsername {
+		t.Errorf("SenderID propogate correctly, %s vs %s",
+			me.eventReceive.senderUsername, senderUsername)
+	}
+
+	if me.eventReceive.timestamp != ts {
+		t.Errorf("Message timestamp did not propogate correctly, "+
+			"%s vs %s", me.eventReceive.timestamp, ts)
+	}
+
+	if me.eventReceive.lease != lease {
+		t.Errorf("Message lease did not propogate correctly, %s vs %s",
+			me.eventReceive.lease, lease)
+	}
+
+	if me.eventReceive.round.ID != r.ID {
+		t.Errorf("Message round did not propogate correctly, %d vs %d",
+			me.eventReceive.round.ID, r.ID)
+	}
+}
+
+func TestEvents_receiveReaction_InvalidReactionMessageID(t *testing.T) {
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	//craft the input for the event
+	chID := &id.ID{}
+	chID[0] = 1
+
+	replyMsgId := []byte("blarg")
+
+	textPayload := &CMIXChannelReaction{
+		Version:           0,
+		Reaction:          "🍆",
+		ReactionMessageID: replyMsgId[:],
+	}
+
+	textMarshaled, err := proto.Marshal(textPayload)
+	if err != nil {
+		t.Fatalf("failed to marshael the message proto: %+v", err)
+	}
+
+	msgID := cryptoChannel.MakeMessageID(textMarshaled)
+
+	senderUsername := "Alice"
+	ts := time.Now()
+
+	lease := 69 * time.Minute
+
+	r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)}
+	r.Timestamps[states.QUEUED] = time.Now()
+
+	//call the handler
+	e.receiveReaction(chID, msgID, 0, senderUsername,
+		textMarshaled, ts, lease, r)
+
+	//check the results on the model
+	if me.eventReceive.channelID != nil {
+		t.Errorf("Channel ID did propogated correctly when the reaction " +
+			"is bad")
+	}
+
+	if me.eventReceive.messageID.Equals(msgID) {
+		t.Errorf("Message ID propogated correctly when the reaction is " +
+			"bad")
+	}
+
+	if !me.eventReceive.reactionTo.Equals(cryptoChannel.MessageID{}) {
+		t.Errorf("Reaction ID propogated correctly when the reaction " +
+			"is bad")
+	}
+
+	if me.eventReceive.senderUsername != "" {
+		t.Errorf("SenderID propogated correctly when the reaction " +
+			"is bad")
+	}
+
+	if me.eventReceive.lease != 0 {
+		t.Errorf("Message lease propogated correctly when the " +
+			"reaction is bad")
+	}
+}
+
+// todo: enable once ValidateReaction works
+/*
+func TestEvents_receiveReaction_InvalidReactionContent(t *testing.T){
+	me := &MockEvent{}
+
+	e := initEvents(me)
+
+	//craft the input for the event
+	chID := &id.ID{}
+	chID[0]=1
+
+	replyMsgId := []byte("blarg")
+
+	textPayload := &CMIXChannelReaction{
+		Version:        0,
+		Reaction:           "Im not a reaction",
+		ReactionMessageID: replyMsgId[:],
+	}
+
+	textMarshaled, err := proto.Marshal(textPayload)
+	if err!=nil{
+		t.Fatalf("failed to marshael the message proto: %+v", err)
+	}
+
+	msgID := cryptoChannel.MakeMessageID(textMarshaled)
+
+	senderUsername := "Alice"
+	ts := time.Now()
+
+	lease := 69*time.Minute
+
+	r := rounds.Round{ID: 420, Timestamps: make(map[states.Round]time.Time)}
+	r.Timestamps[states.QUEUED]=time.Now()
+
+
+	//call the handler
+	e.receiveReaction(chID, msgID, 0, senderUsername,
+		textMarshaled, ts, lease, r)
+
+	//check the results on the model
+	if me.eventReceive.channelID!=nil{
+		t.Errorf("Channel ID did propogated correctly when the reaction " +
+			"is bad")
+	}
+
+	if me.eventReceive.messageID.Equals(msgID){
+		t.Errorf("Message ID propogated correctly when the reaction is " +
+			"bad")
+	}
+
+	if !me.eventReceive.reactionTo.Equals(cryptoChannel.MessageID{}){
+		t.Errorf("Reaction ID propogated correctly when the reaction " +
+			"is bad")
+	}
+
+	if me.eventReceive.senderUsername!=""{
+		t.Errorf("SenderID propogated correctly when the reaction " +
+			"is bad")
+	}
+
+	if me.eventReceive.lease!=0{
+		t.Errorf("Message lease propogated correctly when the " +
+			"reaction is bad")
+	}
+}*/
+
+func getFuncName(i interface{}) string {
+	return runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
+}
diff --git a/channels/messages.go b/channels/messages.go
index 15ec90f8a..b4de7747a 100644
--- a/channels/messages.go
+++ b/channels/messages.go
@@ -12,14 +12,14 @@ import (
 	"gitlab.com/elixxir/crypto/channel"
 )
 
-// UserMessageInternal is the internal structure of a UserMessage protobuf.
-type UserMessageInternal struct {
+// userMessageInternal is the internal structure of a UserMessage protobuf.
+type userMessageInternal struct {
 	userMessage    *UserMessage
 	channelMessage *ChannelMessage
 	messageID      channel.MessageID
 }
 
-func NewUserMessageInternal(ursMsg *UserMessage) (*UserMessageInternal, error) {
+func newUserMessageInternal(ursMsg *UserMessage) (*userMessageInternal, error) {
 	chanMessage := &ChannelMessage{}
 	err := proto.Unmarshal(ursMsg.Message, chanMessage)
 	if err != nil {
@@ -27,14 +27,14 @@ func NewUserMessageInternal(ursMsg *UserMessage) (*UserMessageInternal, error) {
 	}
 
 	channelMessage := chanMessage
-	return &UserMessageInternal{
+	return &userMessageInternal{
 		userMessage:    ursMsg,
 		channelMessage: channelMessage,
 		messageID:      channel.MakeMessageID(ursMsg.Message),
 	}, nil
 }
 
-func UnmarshalUserMessageInternal(usrMsg []byte) (*UserMessageInternal, error) {
+func unmarshalUserMessageInternal(usrMsg []byte) (*userMessageInternal, error) {
 
 	um := &UserMessage{}
 	if err := proto.Unmarshal(usrMsg, um); err != nil {
@@ -49,25 +49,26 @@ func UnmarshalUserMessageInternal(usrMsg []byte) (*UserMessageInternal, error) {
 
 	channelMessage := chanMessage
 
-	return &UserMessageInternal{
+	return &userMessageInternal{
 		userMessage:    um,
 		channelMessage: channelMessage,
+		messageID:      channel.MakeMessageID(um.Message),
 	}, nil
 }
 
 // GetUserMessage retrieves the UserMessage within
-// UserMessageInternal.
-func (umi *UserMessageInternal) GetUserMessage() *UserMessage {
+// userMessageInternal.
+func (umi *userMessageInternal) GetUserMessage() *UserMessage {
 	return umi.userMessage
 }
 
 // GetChannelMessage retrieves the ChannelMessage within
-// UserMessageInternal.
-func (umi *UserMessageInternal) GetChannelMessage() *ChannelMessage {
+// userMessageInternal.
+func (umi *userMessageInternal) GetChannelMessage() *ChannelMessage {
 	return umi.channelMessage
 }
 
 // GetMessageID retrieves the messageID for the message.
-func (umi *UserMessageInternal) GetMessageID() channel.MessageID {
+func (umi *userMessageInternal) GetMessageID() channel.MessageID {
 	return umi.messageID
 }
diff --git a/channels/messages_test.go b/channels/messages_test.go
index afcb89d56..14b54553a 100644
--- a/channels/messages_test.go
+++ b/channels/messages_test.go
@@ -14,27 +14,27 @@ import (
 	"testing"
 )
 
-func TestUserMessageInternal_GetChannelMessage(t *testing.T) {
-	channelMsg := &ChannelMessage{
-		Lease:       69,
-		RoundID:     42,
-		PayloadType: 7,
-		Payload:     []byte("ban_badUSer"),
+func TestUnmarshalUserMessageInternal(t *testing.T) {
+	internal, usrMsg, _ := builtTestUMI(t, 7)
+
+	usrMsgMarshaled, err := proto.Marshal(usrMsg)
+	if err != nil {
+		t.Fatalf("Failed to marshal user message: %+v", err)
 	}
 
-	serialized, err := proto.Marshal(channelMsg)
+	umi, err := unmarshalUserMessageInternal(usrMsgMarshaled)
 	if err != nil {
-		t.Fatalf("Marshal error: %v", err)
+		t.Fatalf("Failed to unmarshal user message: %+v", err)
 	}
 
-	usrMsg := &UserMessage{
-		Message:             serialized,
-		ValidationSignature: []byte("sig"),
-		Signature:           []byte("sig"),
-		Username:            "hunter",
+	if !umi.GetMessageID().Equals(internal.messageID) {
+		t.Errorf("Message IDs were changed in the unmarshal "+
+			"process, %s vs %s", internal.messageID, umi.GetMessageID())
 	}
+}
 
-	internal, _ := NewUserMessageInternal(usrMsg)
+func TestUserMessageInternal_GetChannelMessage(t *testing.T) {
+	internal, _, channelMsg := builtTestUMI(t, 7)
 	received := internal.GetChannelMessage()
 
 	if !reflect.DeepEqual(received.Payload, channelMsg.Payload) ||
@@ -48,28 +48,7 @@ func TestUserMessageInternal_GetChannelMessage(t *testing.T) {
 }
 
 func TestUserMessageInternal_GetUserMessage(t *testing.T) {
-	channelMsg := &ChannelMessage{
-		Lease:       69,
-		RoundID:     42,
-		PayloadType: 7,
-		Payload:     []byte("ban_badUSer"),
-	}
-
-	serialized, err := proto.Marshal(channelMsg)
-	if err != nil {
-		t.Fatalf("Marshal error: %v", err)
-	}
-
-	usrMsg := &UserMessage{
-		Message:             serialized,
-		ValidationSignature: []byte("sig"),
-		Signature:           []byte("sig2"),
-		Username:            "hunter2",
-		ECCPublicKey:        []byte("key"),
-		UsernameLease:       666,
-	}
-
-	internal, _ := NewUserMessageInternal(usrMsg)
+	internal, usrMsg, _ := builtTestUMI(t, 7)
 	received := internal.GetUserMessage()
 
 	if !reflect.DeepEqual(received.Message, usrMsg.Message) ||
@@ -85,28 +64,7 @@ func TestUserMessageInternal_GetUserMessage(t *testing.T) {
 }
 
 func TestUserMessageInternal_GetMessageID(t *testing.T) {
-	channelMsg := &ChannelMessage{
-		Lease:       69,
-		RoundID:     42,
-		PayloadType: 7,
-		Payload:     []byte("ban_badUSer"),
-	}
-
-	serialized, err := proto.Marshal(channelMsg)
-	if err != nil {
-		t.Fatalf("Marshal error: %v", err)
-	}
-
-	usrMsg := &UserMessage{
-		Message:             serialized,
-		ValidationSignature: []byte("sig"),
-		Signature:           []byte("sig2"),
-		Username:            "hunter2",
-		ECCPublicKey:        []byte("key"),
-		UsernameLease:       666,
-	}
-
-	internal, _ := NewUserMessageInternal(usrMsg)
+	internal, usrMsg, _ := builtTestUMI(t, 7)
 	received := internal.GetMessageID()
 
 	expected := channel.MakeMessageID(usrMsg.Message)
@@ -125,10 +83,22 @@ func TestUserMessageInternal_GetMessageID(t *testing.T) {
 func TestUserMessageInternal_GetMessageID_Consistency(t *testing.T) {
 	expected := "ChMsgID-cfw4O6M47N9pqdtTcQjm/SSVqehTPGQd7cAMrNP9bcc="
 
+	internal, _, _ := builtTestUMI(t, 7)
+
+	received := internal.GetMessageID()
+
+	if expected != received.String() {
+		t.Fatalf("GetMessageID did not return expected data."+
+			"\nExpected: %v"+
+			"\nReceived: %v", expected, received)
+	}
+}
+
+func builtTestUMI(t *testing.T, mt MessageType) (*userMessageInternal, *UserMessage, *ChannelMessage) {
 	channelMsg := &ChannelMessage{
 		Lease:       69,
 		RoundID:     42,
-		PayloadType: 7,
+		PayloadType: uint32(mt),
 		Payload:     []byte("ban_badUSer"),
 	}
 
@@ -146,12 +116,7 @@ func TestUserMessageInternal_GetMessageID_Consistency(t *testing.T) {
 		UsernameLease:       666,
 	}
 
-	internal, _ := NewUserMessageInternal(usrMsg)
-	received := internal.GetMessageID()
+	internal, _ := newUserMessageInternal(usrMsg)
 
-	if expected != received.String() {
-		t.Fatalf("GetMessageID did not return expected data."+
-			"\nExpected: %v"+
-			"\nReceived: %v", expected, received)
-	}
+	return internal, usrMsg, channelMsg
 }
diff --git a/channels/userListener.go b/channels/userListener.go
index 366342457..a69de61f3 100644
--- a/channels/userListener.go
+++ b/channels/userListener.go
@@ -31,7 +31,7 @@ func (gul *userListener) Listen(payload []byte,
 	}
 
 	//Decode the message as a user message
-	umi, err := UnmarshalUserMessageInternal(payloadUnpadded)
+	umi, err := unmarshalUserMessageInternal(payloadUnpadded)
 	if err != nil {
 		jww.WARN.Printf("Failed to unmarshal User Message on "+
 			"channel %s", gul.chID)
-- 
GitLab