Skip to content
Snippets Groups Projects
Commit 87c2ff73 authored by Benjamin Wenger's avatar Benjamin Wenger
Browse files

Merge branch 'XX-2645/TestingFixes' into 'peppa/newClient'

Modify tests for completeness and configurability

See merge request !431
parents df8e70fe c86af156
No related branches found
No related tags found
No related merge requests found
......@@ -259,7 +259,7 @@ func (c *Client) StartNetworkFollower() error {
}
c.runner.Add(stopFollow)
// Key exchange
c.runner.Add(keyExchange.Start(c.switchboard, c.storage, c.network))
c.runner.Add(keyExchange.Start(c.switchboard, c.storage, c.network, params.GetDefaultRekey()))
err = c.status.toRunning()
if err != nil {
......
package params
import "time"
type Rekey struct {
RoundTimeout time.Duration
}
func GetDefaultRekey() Rekey {
return Rekey{
RoundTimeout: time.Minute,
}
}
......@@ -29,15 +29,24 @@ func TestHandleConfirm(t *testing.T) {
// Generate a session ID, bypassing some business logic here
sessionID := GeneratePartnerID(alicePrivKey, bobPubKey, genericGroup)
// Get Alice's manager for Bob
receivedManager, err := aliceSession.E2e().GetPartner(bobID)
if err != nil {
t.Errorf("Bob is not recognized as Alice's partner: %v", err)
}
// Trigger negotiations, so that negotiation statuses
// can be transitioned
receivedManager.TriggerNegotiations()
// Generate the message
rekey, _ := proto.Marshal(&RekeyConfirm{
SessionID: sessionID.Marshal(),
})
payload := make([]byte, 0)
payload = append(payload, rekey...)
receiveMsg := message.Receive{
Payload: payload,
Payload: rekey,
MessageType: message.NoType,
Sender: bobID,
Timestamp: time.Now(),
......@@ -46,4 +55,17 @@ func TestHandleConfirm(t *testing.T) {
// Handle the confirmation
handleConfirm(aliceSession, receiveMsg)
// Get Alice's session for Bob
confirmedSession := receivedManager.GetSendSession(sessionID)
// Check that the session is in the proper status
newSession := receivedManager.GetSendSession(sessionID)
if newSession.NegotiationStatus() != e2e.Confirmed {
t.Errorf("Session not in confirmed status!" +
"\n\tExpected: Confirmed" +
"\n\tReceived: %s", confirmedSession.NegotiationStatus())
}
}
......@@ -3,6 +3,7 @@ package keyExchange
import (
"gitlab.com/elixxir/client/interfaces"
"gitlab.com/elixxir/client/interfaces/message"
"gitlab.com/elixxir/client/interfaces/params"
"gitlab.com/elixxir/client/stoppable"
"gitlab.com/elixxir/client/storage"
"gitlab.com/elixxir/client/switchboard"
......@@ -14,8 +15,8 @@ const keyExchangeTriggerName = "KeyExchangeTrigger"
const keyExchangeConfirmName = "KeyExchangeConfirm"
const keyExchangeMulti = "KeyExchange"
func Start(switchboard *switchboard.Switchboard, sess *storage.Session,
net interfaces.NetworkManager) stoppable.Stoppable {
func Start(switchboard *switchboard.Switchboard, sess *storage.Session, net interfaces.NetworkManager,
params params.Rekey) stoppable.Stoppable {
// register the rekey trigger thread
triggerCh := make(chan message.Receive, 100)
......@@ -31,7 +32,7 @@ func Start(switchboard *switchboard.Switchboard, sess *storage.Session,
})
// start the trigger thread
go startTrigger(sess, net, triggerCh, triggerStop.Quit())
go startTrigger(sess, net, triggerCh, triggerStop.Quit(), params)
//register the rekey confirm thread
confirmCh := make(chan message.Receive, 100)
......
......@@ -4,6 +4,7 @@ import (
"github.com/golang/protobuf/proto"
"gitlab.com/elixxir/client/interfaces"
"gitlab.com/elixxir/client/interfaces/message"
"gitlab.com/elixxir/client/interfaces/params"
"gitlab.com/elixxir/client/storage"
"gitlab.com/elixxir/client/storage/e2e"
"gitlab.com/elixxir/client/switchboard"
......@@ -38,8 +39,10 @@ func TestFullExchange(t *testing.T) {
e2e.GetDefaultSessionParams(), e2e.GetDefaultSessionParams())
// Start the listeners for alice and bob
Start(aliceSwitchboard, aliceSession, aliceManager)
Start(bobSwitchboard, bobSession, bobManager)
rekeyParams := params.GetDefaultRekey()
rekeyParams.RoundTimeout = 5 * time.Second
Start(aliceSwitchboard, aliceSession, aliceManager, rekeyParams)
Start(bobSwitchboard, bobSession, bobManager, rekeyParams)
// Generate a session ID, bypassing some business logic here
sessionID := GeneratePartnerID(alicePrivKey, bobPubKey, genericGroup)
......
......@@ -24,10 +24,10 @@ import (
)
func CheckKeyExchanges(instance *network.Instance, sendE2E interfaces.SendE2E,
sess *storage.Session, manager *e2e.Manager) {
sess *storage.Session, manager *e2e.Manager, sendTimeout time.Duration) {
sessions := manager.TriggerNegotiations()
for _, session := range sessions {
go trigger(instance, sendE2E, sess, manager, session)
go trigger(instance, sendE2E, sess, manager, session, sendTimeout)
}
}
......@@ -36,7 +36,8 @@ func CheckKeyExchanges(instance *network.Instance, sendE2E interfaces.SendE2E,
// session. They run the same negotiation, the former does it on a newly created
// session while the latter on an extand
func trigger(instance *network.Instance, sendE2E interfaces.SendE2E,
sess *storage.Session, manager *e2e.Manager, session *e2e.Session) {
sess *storage.Session, manager *e2e.Manager, session *e2e.Session,
sendTimeout time.Duration) {
var negotiatingSession *e2e.Session
switch session.NegotiationStatus() {
// If the passed session is triggering a negotiation on a new session to
......@@ -56,7 +57,7 @@ func trigger(instance *network.Instance, sendE2E interfaces.SendE2E,
}
// send the rekey notification to the partner
err := negotiate(instance, sendE2E, sess, negotiatingSession)
err := negotiate(instance, sendE2E, sess, negotiatingSession, sendTimeout)
// if sending the negotiation fails, revert the state of the session to
// unconfirmed so it will be triggered in the future
if err != nil {
......@@ -66,7 +67,8 @@ func trigger(instance *network.Instance, sendE2E interfaces.SendE2E,
}
func negotiate(instance *network.Instance, sendE2E interfaces.SendE2E,
sess *storage.Session, session *e2e.Session) error {
sess *storage.Session, session *e2e.Session,
sendTimeout time.Duration) error {
e2eStore := sess.E2e()
//generate public key
......@@ -111,7 +113,7 @@ func negotiate(instance *network.Instance, sendE2E interfaces.SendE2E,
//Register the event for all rounds
roundEvents := instance.GetRoundEvents()
for _, r := range rounds {
roundEvents.AddRoundEventChan(r, sendResults, 1*time.Minute,
roundEvents.AddRoundEventChan(r, sendResults, sendTimeout,
states.COMPLETED, states.FAILED)
}
......
......@@ -14,7 +14,6 @@ import (
ds "gitlab.com/elixxir/comms/network/dataStructures"
"gitlab.com/elixxir/crypto/cyclic"
"gitlab.com/elixxir/primitives/states"
"time"
)
const (
......@@ -23,13 +22,13 @@ const (
)
func startTrigger(sess *storage.Session, net interfaces.NetworkManager,
c chan message.Receive, quitCh <-chan struct{}) {
c chan message.Receive, quitCh <-chan struct{}, params params.Rekey) {
for true {
select {
case <-quitCh:
return
case request := <-c:
err := handleTrigger(sess, net, request)
err := handleTrigger(sess, net, request, params)
if err != nil {
jww.ERROR.Printf("Failed to handle rekey trigger: %s",
err)
......@@ -39,7 +38,7 @@ func startTrigger(sess *storage.Session, net interfaces.NetworkManager,
}
func handleTrigger(sess *storage.Session, net interfaces.NetworkManager,
request message.Receive) error {
request message.Receive, param params.Rekey) error {
//ensure the message was encrypted properly
if request.Encryption != message.E2E {
errMsg := fmt.Sprintf(errBadTrigger, request.Sender)
......@@ -122,14 +121,17 @@ func handleTrigger(sess *storage.Session, net interfaces.NetworkManager,
sendResults := make(chan ds.EventReturn, len(rounds))
roundEvents := net.GetInstance().GetRoundEvents()
for _, r := range rounds {
roundEvents.AddRoundEventChan(r, sendResults, 1*time.Minute,
roundEvents.AddRoundEventChan(r, sendResults, param.RoundTimeout,
states.COMPLETED, states.FAILED)
}
fmt.Println("before tracking")
//Wait until the result tracking responds
success, numTimeOut, numRoundFail := utility.TrackResults(sendResults, len(rounds))
// If a single partition of the Key Negotiation request does not
// transmit, the partner will not be able to read the confirmation. If
// such a failure occurs
fmt.Println("after tracking")
if !success {
jww.ERROR.Printf("Key Negotiation for %s failed to "+
"transmit %v/%v paritions: %v round failures, %v timeouts",
......
......@@ -2,7 +2,10 @@ package keyExchange
import (
"gitlab.com/elixxir/client/interfaces/message"
"gitlab.com/elixxir/client/interfaces/params"
"gitlab.com/elixxir/client/storage/e2e"
"gitlab.com/elixxir/crypto/csprng"
dh "gitlab.com/elixxir/crypto/diffieHellman"
"gitlab.com/xx_network/primitives/id"
"google.golang.org/protobuf/proto"
"testing"
......@@ -19,6 +22,10 @@ func TestHandleTrigger(t *testing.T) {
alicePrivKey := aliceSession.E2e().GetDHPrivateKey()
bobPubKey := bobSession.E2e().GetDHPublicKey()
// Generate bob's new keypair
newBobPrivKey := dh.GeneratePrivateKey(dh.DefaultPrivateKeyLength, genericGroup, csprng.NewSystemRNG())
newBobPubKey := dh.GeneratePublicKey(newBobPrivKey, genericGroup)
// Maintain an ID for bob
bobID := id.NewIdFromBytes([]byte("test"), t)
......@@ -27,19 +34,16 @@ func TestHandleTrigger(t *testing.T) {
e2e.GetDefaultSessionParams(), e2e.GetDefaultSessionParams())
// Generate a session ID, bypassing some business logic here
sessionID := GeneratePartnerID(alicePrivKey, bobPubKey, genericGroup)
oldSessionID := GeneratePartnerID(alicePrivKey, bobPubKey, genericGroup)
// Generate the message
rekey, _ := proto.Marshal(&RekeyTrigger{
SessionID: sessionID.Marshal(),
PublicKey: bobPubKey.Bytes(),
SessionID: oldSessionID.Marshal(),
PublicKey: newBobPubKey.Bytes(),
})
payload := make([]byte, 0)
payload = append(payload, rekey...)
receiveMsg := message.Receive{
Payload: payload,
Payload: rekey,
MessageType: message.NoType,
Sender: bobID,
Timestamp: time.Now(),
......@@ -47,8 +51,43 @@ func TestHandleTrigger(t *testing.T) {
}
// Handle the trigger and check for an error
err := handleTrigger(aliceSession, aliceManager, receiveMsg)
rekeyParams := params.GetDefaultRekey()
rekeyParams.RoundTimeout = 0 * time.Second
err := handleTrigger(aliceSession, aliceManager, receiveMsg, rekeyParams)
if err != nil {
t.Errorf("Handle trigger error: %v", err)
}
// Get Alice's manager for reception from Bob
receivedManager, err := aliceSession.E2e().GetPartner(bobID)
if err != nil {
t.Errorf("Failed to get bob's manager: %v", err)
}
// Generate the new session ID based off of Bob's new keys
baseKey := dh.GenerateSessionKey(alicePrivKey, newBobPubKey, genericGroup)
newSessionID := e2e.GetSessionIDFromBaseKeyForTesting(baseKey, t)
// Check that this new session ID is now in the manager
newSession := receivedManager.GetReceiveSession(newSessionID)
if newSession == nil {
t.Errorf("Did not get expected session")
}
// Generate a keypair alice will not recognize
unknownPrivateKey := dh.GeneratePrivateKey(dh.DefaultPrivateKeyLength, genericGroup, csprng.NewSystemRNG())
unknownPubliceKey := dh.GeneratePublicKey(unknownPrivateKey, genericGroup)
// Generate a new session ID based off of these unrecognized keys
badSessionID := e2e.GetSessionIDFromBaseKeyForTesting(unknownPubliceKey, t)
// Check that this session with unrecognized keys is not valid
badSession := receivedManager.GetReceiveSession(badSessionID)
if badSession != nil {
t.Errorf("Alice found a session from an unknown keypair. " +
"\nSession: %v", badSession)
}
}
......@@ -45,15 +45,15 @@ type testNetworkManagerGeneric struct {
}
func (t *testNetworkManagerGeneric) GetHealthTracker() interfaces.HealthTracker {
panic("implement me")
return nil
}
func (t *testNetworkManagerGeneric) Follow() (stoppable.Stoppable, error) {
panic("implement me")
return nil, nil
}
func (t *testNetworkManagerGeneric) CheckGarbledMessages() {
panic("implement me")
return
}
func (t *testNetworkManagerGeneric) SendE2E(m message.Send, p params.E2E) ([]id.Round, error) {
......@@ -131,15 +131,15 @@ type testNetworkManagerFullExchange struct {
}
func (t *testNetworkManagerFullExchange) GetHealthTracker() interfaces.HealthTracker {
panic("implement me")
return nil
}
func (t *testNetworkManagerFullExchange) Follow() (stoppable.Stoppable, error) {
panic("implement me")
return nil, nil
}
func (t *testNetworkManagerFullExchange) CheckGarbledMessages() {
panic("implement me")
return
}
// Intended for alice to send to bob. Trigger's Bob's confirmation, chaining the operation
......
......@@ -72,7 +72,7 @@ func (m *Manager) SendE2E(msg message.Send, param params.E2E) ([]id.Round, error
// while waiting check if any rekeys need to happen and trigger them. This
// can happen now because the key popping happens in this thread,
// only the sending is parallelized
keyExchange.CheckKeyExchanges(m.Instance, m.SendE2E, m.Session, partner)
keyExchange.CheckKeyExchanges(m.Instance, m.SendE2E, m.Session, partner, 1*time.Minute)
wg.Wait()
......
......@@ -11,6 +11,7 @@ import (
"fmt"
"github.com/pkg/errors"
jww "github.com/spf13/jwalterweatherman"
"gitlab.com/elixxir/client/globals"
"gitlab.com/elixxir/client/storage/versioned"
"gitlab.com/elixxir/crypto/cyclic"
dh "gitlab.com/elixxir/crypto/diffieHellman"
......@@ -18,6 +19,7 @@ import (
"gitlab.com/elixxir/crypto/hash"
"gitlab.com/xx_network/primitives/id"
"sync"
"testing"
"time"
)
......@@ -216,6 +218,23 @@ func getSessionIDFromBaseKey(baseKey *cyclic.Int) SessionID {
return sid
}
//underlying definition of session id
// FOR TESTING PURPOSES ONLY
func GetSessionIDFromBaseKeyForTesting(baseKey *cyclic.Int, i interface{}) SessionID {
switch i.(type) {
case *testing.T:
break
case *testing.M:
break
case *testing.B:
break
default:
globals.Log.FATAL.Panicf("GetSessionIDFromBaseKeyForTesting is restricted to testing only. Got %T", i)
}
return getSessionIDFromBaseKey(baseKey)
}
//Blake2B hash of base key used for storage
func (s *Session) GetID() SessionID {
return getSessionIDFromBaseKey(s.baseKey)
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment