func mockComponentConnection(t *testing.T, port int, handler func(t *testing.T, sc *ServerConn)) (*Component, *ServerMock) {
	testComponentAddress := fmt.Sprintf("%s:%d", testComponentDomain, port)
	mock := &ServerMock{}
	mock.Start(t, testComponentAddress, handler)
	c := makeBasicComponent(defaultComponentName, testComponentAddress, t)
	err := c.Connect()
	if err != nil {
		t.Errorf("%+v", err)
	}
	return c, mock
}
=============================================================================
Basic XMPP Server Mock Handlers.
===============================
Init mock server and connection
Creating a mock server and connecting a Component to it. Initialized with given port and handler function
The Component and mock are both returned
package xmpp
import (
	"context"
	"encoding/xml"
	"errors"
	"fmt"
	"strings"
	"testing"
	"time"
	"github.com/google/uuid"
	"gosrc.io/xmpp/stanza"
)
const (
	defaultChannelTimeout = 5 * time.Second
)
func TestHandshake(t *testing.T) {
	opts := ComponentOptions{
		Domain: "test.localhost",
		Secret: "mypass",
	}
	c := Component{ComponentOptions: opts}
	streamID := "1263952298440005243"
	expected := "c77e2ef0109fbbc5161e83b51629cd1353495332"
	result := c.handshake(streamID)
	if result != expected {
		t.Errorf("incorrect handshake calculation '%s' != '%s'", result, expected)
	}
}
func TestGenerateHandshakeId(t *testing.T) {
	clientDone := make(chan struct{})
	serverDone := make(chan struct{})
	var uuidsArray = [5]string{}
	for i := 1; i < len(uuidsArray); i++ {
		id, _ := uuid.NewRandom()
		uuidsArray[i] = id.String()
	}
	var uchan = make(chan string, len(uuidsArray))
	for _, elt := range uuidsArray {
		uchan <- elt
	}
	h := func(t *testing.T, sc *ServerConn) {
		checkOpenStreamHandshakeID(t, sc, <-uchan)
		readHandshakeComponent(t, sc.decoder)
		sc.connection.Write([]byte("<handshake/>"))  
		serverDone <- struct{}{}
	}
	testComponentAddess := fmt.Sprintf("%s:%d", testComponentDomain, testHandshakePort)
	mock := ServerMock{}
	mock.Start(t, testComponentAddess, h)
	opts := ComponentOptions{
		TransportConfiguration: TransportConfiguration{
			Address: testComponentAddess,
			Domain:  "localhost",
		},
		Domain:   testComponentDomain,
		Secret:   "mypass",
		Name:     "Test Component",
		Category: "gateway",
		Type:     "service",
	}
	router := NewRouter()
	c, err := NewComponent(opts, router, componentDefaultErrorHandler)
	if err != nil {
		t.Errorf("%+v", err)
	}
	c.transport, err = NewComponentTransport(c.ComponentOptions.TransportConfiguration)
	if err != nil {
		t.Errorf("%+v", err)
	}
	go func() {
		m := make(map[string]bool)
		for range uuidsArray {
			idChan := make(chan string)
			go func() {
				streamId, err := c.transport.Connect()
				if err != nil {
					t.Fatalf("failed to mock component connection to get a handshake: %s", err)
				}
				idChan <- streamId
			}()
			var streamId string
			select {
			case streamId = <-idChan:
			case <-time.After(defaultTimeout):
				t.Fatalf("test timed out")
			}
			hs := stanza.Handshake{
				Value: c.handshake(streamId),
			}
			m[hs.Value] = true
			hsRaw, err := xml.Marshal(hs)
			if err != nil {
				t.Fatalf("could not marshal handshake: %s", err)
			}
			c.SendRaw(string(hsRaw))
			waitForEntity(t, serverDone)
			c.transport.Close()
		}
		if len(uuidsArray) != len(m) {
			t.Errorf("Handshake does not produce a unique id. Expected: %d unique ids, got: %d", len(uuidsArray), len(m))
		}
		clientDone <- struct{}{}
	}()
	waitForEntity(t, clientDone)
	mock.Stop()
}
func TestStreamManager(t *testing.T) {
	NewStreamManager(&Component{}, nil)
}
func TestDecoder(t *testing.T) {
	c, _ := mockComponentConnection(t, testDecoderPort, handlerForComponentHandshakeDefaultID)
	if c.transport.GetDecoder() == nil {
		t.Errorf("Failed to initialize decoder. Decoder is nil.")
	}
}
func TestSendIq(t *testing.T) {
	serverDone := make(chan struct{})
	clientDone := make(chan struct{})
	h := func(t *testing.T, sc *ServerConn) {
		handlerForComponentIQSend(t, sc)
		serverDone <- struct{}{}
	}
	c, m := mockComponentConnection(t, testSendIqPort, h)
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	iqReq, err := stanza.NewIQ(stanza.Attrs{Type: stanza.IQTypeGet, From: "test1@localhost/mremond-mbp", To: defaultServerName, Id: defaultStreamID, Lang: "en"})
	if err != nil {
		t.Fatalf("failed to create IQ request: %v", err)
	}
	disco := iqReq.DiscoInfo()
	iqReq.Payload = disco
	errChan := make(chan error)
	errorHandler := func(err error) {
		errChan <- err
	}
	c.ErrorHandler = errorHandler
	go func() {
		var res chan stanza.IQ
		res, _ = c.SendIQ(ctx, iqReq)
		select {
		case <-res:
		case err := <-errChan:
			t.Fatalf(err.Error())
		}
		clientDone <- struct{}{}
	}()
	waitForEntity(t, clientDone)
	waitForEntity(t, serverDone)
	cancel()
	m.Stop()
}
func TestSendIqFail(t *testing.T) {
	done := make(chan struct{})
	h := func(t *testing.T, sc *ServerConn) {
		handlerForComponentIQSend(t, sc)
		done <- struct{}{}
	}
	c, m := mockComponentConnection(t, testSendIqFailPort, h)
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	iqReq, err := stanza.NewIQ(stanza.Attrs{Type: stanza.IQTypeGet, From: "test1@localhost/mremond-mbp", To: defaultServerName, Id: defaultStreamID, Lang: "en"})
	if err != nil {
		t.Fatalf("failed to create IQ request: %v", err)
	}
	iqReq.Id = ""
	disco := iqReq.DiscoInfo()
	iqReq.Payload = disco
	errChan := make(chan error)
	errorHandler := func(err error) {
		errChan <- err
	}
	c.ErrorHandler = errorHandler
	var res chan stanza.IQ
	res, _ = c.SendIQ(ctx, iqReq)
	select {
	case r := <-res:  
		t.Errorf("We should not be getting an IQ response here : this should fail !")
		fmt.Println(r)
	case <-errChan:  
	case <-time.After(defaultChannelTimeout):  
		t.Errorf("Failed to receive response, to sent IQ, from mock server")
	}
	select {
	case <-done:
		m.Stop()
	case <-time.After(defaultChannelTimeout):
		t.Errorf("The mock server failed to finish its job !")
	}
	cancel()
}
func TestSendRaw(t *testing.T) {
	done := make(chan struct{})
	h := func(t *testing.T, sc *ServerConn) {
		handlerForComponentHandshakeDefaultID(t, sc)
		respondToIQ(t, sc)
		done <- struct{}{}
	}
	type testCase struct {
		req       string
		shouldErr bool
		port      int
	}
	testRequests := make(map[string]testCase)
	testRequests["Correct IQ"] = testCase{
		req:       `<iq type="get" id="91bd0bba-012f-4d92-bb17-5fc41e6fe545" from="test1@localhost/mremond-mbp" to="testServer" lang="en"><query xmlns="http://jabber.org/protocol/disco#info"></query></iq>`,
		shouldErr: false,
		port:      testSendRawPort + 100,
	}
	testRequests["IQ with missing ID"] = testCase{
		req:       `<iq type="get" from="test1@localhost/mremond-mbp" to="testServer" lang="en"><query xmlns="http://jabber.org/protocol/disco#info"></query></iq>`,
		shouldErr: true,
		port:      testSendRawPort + 200,
	}
	errChan := make(chan error)
	errHandler := func(err error) {
		errChan <- err
	}
	for name, tcase := range testRequests {
		t.Run(name, func(st *testing.T) {
			c, m := mockComponentConnection(t, tcase.port, h)
			c.ErrorHandler = errHandler
			err := c.SendRaw(tcase.req)
			if err != nil {
				t.Errorf("Error sending Raw string")
			}
			select {
			case <-time.After(200 * time.Millisecond):
			case err = <-errChan:
				if err == nil && tcase.shouldErr {
					t.Errorf("Failed to get closing stream err")
				} else if err != nil && !tcase.shouldErr {
					t.Errorf("This test is not supposed to err ! => %s", err.Error())
				}
			}
			c.transport.Close()
			select {
			case <-done:
				m.Stop()
			case <-time.After(defaultChannelTimeout):
				t.Errorf("The mock server failed to finish its job !")
			}
		})
	}
}
func TestDisconnect(t *testing.T) {
	c, m := mockComponentConnection(t, testDisconnectPort, handlerForComponentHandshakeDefaultID)
	err := c.transport.Ping()
	if err != nil {
		t.Errorf("Could not ping but not disconnected yet")
	}
	c.Disconnect()
	err = c.transport.Ping()
	if err == nil {
		t.Errorf("Did not disconnect properly")
	}
	m.Stop()
}
func TestStreamManagerDisconnect(t *testing.T) {
	testComponentAddress := fmt.Sprintf("%s:%d", testComponentDomain, testSManDisconnectPort)
	mock := ServerMock{}
	mock.Start(t, testComponentAddress, handlerComponentFailedHandshakeDefaultID)
	c := makeBasicComponent(defaultComponentName, testComponentAddress, t)
	cm := NewStreamManager(c, nil)
	errChan := make(chan error)
	runSMan := func(errChan chan error) {
		errChan <- cm.Run()
	}
	go runSMan(errChan)
	select {
	case <-errChan:
	case <-time.After(100 * time.Millisecond):
		t.Errorf("The component and server seem to still be connected while they should not.")
	}
	mock.Stop()
}