package mikrotik

import (
	"bytes"
	"testing"
)

func Test_CVE_2018_14847_ServerResponse1(t *testing.T) {
	result := NewM2Message()
	data := "\x01\x00\xff\x88\x02\x00\x00\x00\x00\x00\x08\x00\x00\x00\x02\x00\xff\x88\x02\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\x00\xfe\x09\x06\x03\x00\xff\x09\x02\x02\x00\x00\x09\xbc\x06\x00\xff\x09\x05"

	if !ParseM2Message([]byte(data), result) {
		t.Error("Failed M2 messaging parsing")
	}

	if result.U32s[0xfe0001] != 6 {
		t.Error("u32 var 0xfe0001 was expected to be 6, got", result.U32s[0xfe0001])
	}

	if result.U32s[0xff0003] != 2 {
		t.Error("u32 var 0xff0003 was expected to be 2, got", result.U32s[0xff0003])
	}

	if result.U32s[2] != 0xbc {
		t.Error("u32 var 2 was expected to be 0xbc, got", result.U32s[2])
	}

	if result.U32s[0xff0006] != 5 {
		t.Error("u32 var 0xff0006 was expected to be 5, got", result.U32s[0xff0006])
	}

	if len(result.ArrayU32[0xff0001]) != 2 {
		t.Error("ArrayU32 var 0xff0001 was expected to contain 2 values, has", len(result.ArrayU32[0xff0001]))
	}

	if len(result.ArrayU32[0xff0002]) != 2 {
		t.Error("ArrayU32 var 0xff0002 was expected to contain 2 values, has", len(result.ArrayU32[0xff0002]))
	}

	if result.ArrayU32[0xff0001][0] != 0 {
		t.Error("ArrayU32 var 0xff0001 index 0 was expected to be 0, has", result.ArrayU32[0xff0001][0])
	}

	if result.ArrayU32[0xff0001][1] != 8 {
		t.Error("ArrayU32 var 0xff0001 index 0 was expected to be 8, has", result.ArrayU32[0xff0001][1])
	}

	if result.ArrayU32[0xff0002][0] != 2 {
		t.Error("ArrayU32 var 0xff0002 index 0 was expected to be 2, has", result.ArrayU32[0xff0002][0])
	}

	if result.ArrayU32[0xff0002][1] != 2 {
		t.Error("ArrayU32 var 0xff0002 index 1 was expected to be 2, has", result.ArrayU32[0xff0002][1])
	}

	if result.GetSessionID() != 6 {
		t.Error("The session id was expected to be 6, got", result.GetSessionID())
	}
}

func Test_CVE_2018_14847_ServerResponse2(t *testing.T) {
	result := NewM2Message()
	data := "\x01\x00\xff\x88\x02\x00\x00\x00\x00\x00\x08\x00\x00\x00\x02\x00\xff\x88\x02\x00\x02\x00\x00\x00\x02\x00\x00\x00\x04\x00\x00\x01\x03\x00\xff\x09\x02\x06\x00\xff\x09\x06\x03\x00\x00\x31\xbc\x5a\x00\x4d\x32\x10\x00\x00\xa8\x00\x00\x1c\x00\x00\x00\x0a\x00\xfe\x00\x05\x00\x00\x09\x00\x06\x00\x00\x09\x00\x0b\x00\x00\x08\xfe\xff\x07\x00\x12\x00\x00\x09\x02\x01\x00\xfe\x09\x01\x02\x00\x00\x09\x03\x09\x00\xfe\x21\x13\x73\x79\x73\x74\x65\x6d\x20\x64\x65\x66\x61\x75\x6c\x74\x20\x75\x73\x65\x72\x11\x00\x00\x21\x00\x01\x00\x00\x21\x05\x61\x64\x6d\x69\x6e\x62\x00\x4d\x32\x10\x00\x00\xa8\x00\x00\x1c\x00\x00\x00\x0a\x00\xfe\x00\x05\x00\x00\x09\x00\x06\x00\x00\x09\x00\x1f\x00\x00\x08\x7e\x9e\x07\x00\x0b\x00\x00\x08\xfe\xff\x07\x00\x12\x00\x00\x09\x02\x01\x00\xfe\x09\x01\x02\x00\x00\x09\x03\x09\x00\xfe\x21\x13\x73\x79\x73\x74\x65\x6d\x20\x64\x65\x66\x61\x75\x6c\x74\x20\x75\x73\x65\x72\x11\x00\x00\x21\x00\x01\x00\x00\x21\x05\x61\x64\x6d\x69\x6e"

	if !ParseM2Message([]byte(data), result) {
		t.Error("Failed M2 messaging parsing")
	}

	if len(result.ArrayU32[0xff0001]) != 2 {
		t.Error("ArrayU32 var 0xff0001 was expected to contain 2 values, has", len(result.ArrayU32[0xff0001]))
	}

	if len(result.ArrayU32[0xff0002]) != 2 {
		t.Error("ArrayU32 var 0xff0002 was expected to contain 2 values, has", len(result.ArrayU32[0xff0002]))
	}

	if result.ArrayU32[0xff0001][0] != 0 {
		t.Error("ArrayU32 var 0xff0001 index 0 was expected to be 0, has", result.ArrayU32[0xff0001][0])
	}

	if result.ArrayU32[0xff0001][1] != 8 {
		t.Error("ArrayU32 var 0xff0001 index 0 was expected to be 8, has", result.ArrayU32[0xff0001][1])
	}

	if result.ArrayU32[0xff0002][0] != 2 {
		t.Error("ArrayU32 var 0xff0002 index 0 was expected to be 2, has", result.ArrayU32[0xff0002][0])
	}

	if result.ArrayU32[0xff0002][1] != 2 {
		t.Error("ArrayU32 var 0xff0002 index 1 was expected to be 2, has", result.ArrayU32[0xff0002][1])
	}

	if !result.Bools[4] {
		t.Error("Bools var 4 was expected to be true, was false")
	}

	if len(result.Raw[3]) != 0xbc {
		t.Error("Raw var 3 was expected to contain 0xbc bytes, has", len(result.Raw[3]))
	}

	if !bytes.Equal(result.Raw[3], []byte("\x5a\x00\x4d\x32\x10\x00\x00\xa8\x00\x00\x1c\x00\x00\x00\x0a\x00\xfe\x00\x05\x00\x00\x09\x00\x06\x00\x00\x09\x00\x0b\x00\x00\x08\xfe\xff\x07\x00\x12\x00\x00\x09\x02\x01\x00\xfe\x09\x01\x02\x00\x00\x09\x03\x09\x00\xfe\x21\x13\x73\x79\x73\x74\x65\x6d\x20\x64\x65\x66\x61\x75\x6c\x74\x20\x75\x73\x65\x72\x11\x00\x00\x21\x00\x01\x00\x00\x21\x05\x61\x64\x6d\x69\x6e\x62\x00\x4d\x32\x10\x00\x00\xa8\x00\x00\x1c\x00\x00\x00\x0a\x00\xfe\x00\x05\x00\x00\x09\x00\x06\x00\x00\x09\x00\x1f\x00\x00\x08\x7e\x9e\x07\x00\x0b\x00\x00\x08\xfe\xff\x07\x00\x12\x00\x00\x09\x02\x01\x00\xfe\x09\x01\x02\x00\x00\x09\x03\x09\x00\xfe\x21\x13\x73\x79\x73\x74\x65\x6d\x20\x64\x65\x66\x61\x75\x6c\x74\x20\x75\x73\x65\x72\x11\x00\x00\x21\x00\x01\x00\x00\x21\x05\x61\x64\x6d\x69\x6e")) {
		t.Error("Raw var 3 does not contain the expected payload")
	}
}

func Test_ParseUsersFile(t *testing.T) {
	result := NewM2Message()
	data := "\x5a\x00\x4d\x32\x10\x00\x00\xa8\x00\x00\x1c\x00\x00\x00\x0a\x00\xfe\x00\x05\x00\x00\x09\x00\x06\x00\x00\x09\x00\x0b\x00\x00\x08\xfe\xff\x07\x00\x12\x00\x00\x09\x02\x01\x00\xfe\x09\x01\x02\x00\x00\x09\x03\x09\x00\xfe\x21\x13\x73\x79\x73\x74\x65\x6d\x20\x64\x65\x66\x61\x75\x6c\x74\x20\x75\x73\x65\x72\x11\x00\x00\x21\x00\x01\x00\x00\x21\x05\x61\x64\x6d\x69\x6e\x62\x00\x4d\x32\x10\x00\x00\xa8\x00\x00\x1c\x00\x00\x00\x0a\x00\xfe\x00\x05\x00\x00\x09\x00\x06\x00\x00\x09\x00\x1f\x00\x00\x08\x7e\x9e\x07\x00\x0b\x00\x00\x08\xfe\xff\x07\x00\x12\x00\x00\x09\x02\x01\x00\xfe\x09\x01\x02\x00\x00\x09\x03\x09\x00\xfe\x21\x13\x73\x79\x73\x74\x65\x6d\x20\x64\x65\x66\x61\x75\x6c\x74\x20\x75\x73\x65\x72\x11\x00\x00\x21\x00\x01\x00\x00\x21\x05\x61\x64\x6d\x69\x6e"

	if !ParseM2Message([]byte(data), result) {
		t.Error("Failed M2 messaging parsing")
	}
}

func Test_MessageCreation(t *testing.T) {
	msg := NewM2Message()
	msg.SetTo(2, 2)
	msg.SetCommand(7)
	msg.SetRequestID(2)
	msg.SetReplyExpected(true)
	msg.AddU32(2, 12)
	msg.AddString(1, []byte("test"))

	data := msg.Serialize()

	readit := NewM2Message()
	if !ParseM2Message(data, readit) {
		t.Error("Failed M2 messaging parsing")
	}
}

func Test_FailingDatFileEntry(t *testing.T) {
	result := NewM2Message()
	data := "\x10\x00\x00\xa8\x00\x00\x1c\x00\x00\x01\x0a\x00\xfe\x00\x05\x00\x00\x09\x00\x06\x00\x00\x09\x00\x0b\x00\x00\x08\xfe\xff\x07\x00\x12\x00\x00\x09\x02\x01\x00\xfe\x09\x02\x02\x00\x00\x09\x03\x09\x00\xfe\x21\x0d\x74\x68\x69\x73\x20\x69\x73\x20\x75\x73\x65\x72\x31\x11\x00\x00\x21\x10\x77\x1e\xd0\x02\x57\xd6\x5c\x59\xc4\xba\x83\x1a\x86\x6e\x44\x0e\x01\x00\x00\x21\x05\x75\x73\x65\x72\x31"
	if !ParseM2Message([]byte(data), result) {
		t.Error("Failed M2 messaging parsing")
	}
}
