from udsoncan.client import Client
from udsoncan import services, MemoryLocation, DataFormatIdentifier
from udsoncan.exceptions import *

from test.ClientServerTest import ClientServerTest

class TestRequestUpload(ClientServerTest):
	def __init__(self, *args, **kwargs):
		ClientServerTest.__init__(self, *args, **kwargs)

	def test_request_upload_success(self):
		request = self.conn.touserqueue.get(timeout=0.2)
		self.assertEqual(request, b"\x35\x00\x12\x12\x34\xFF")
		self.conn.fromuserqueue.put(b"\x75\x20\xab\xcd")	# Positive response

	def _test_request_upload_success(self):
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
		response = self.udsclient.request_upload(memory_location=memloc)
		self.assertEqual(response.service_data.max_length,0xabcd)

	def test_request_upload_success_spr_no_effect(self):
		request = self.conn.touserqueue.get(timeout=0.2)
		self.assertEqual(request, b"\x35\x00\x12\x12\x34\xFF")
		self.conn.fromuserqueue.put(b"\x75\x20\xab\xcd")	# Positive response

	def _test_request_upload_success_spr_no_effect(self):
		with self.udsclient.suppress_positive_response:
			memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
			response = self.udsclient.request_upload(memory_location=memloc)
			self.assertEqual(response.service_data.max_length,0xabcd)

	def test_request_upload_config_format(self):
		request = self.conn.touserqueue.get(timeout=0.2)
		self.assertEqual(request, b"\x35\x00\x24\x00\x00\x12\x34\x00\xFF")	# dfi = 24 and 0 padding
		self.conn.fromuserqueue.put(b"\x75\x20\xab\xcd")	# Positive response

	def _test_request_upload_config_format(self):
		self.udsclient.config = {'server_address_format':32, 'server_memorysize_format':16}
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF)
		response = self.udsclient.request_upload(memory_location=memloc)
		self.assertEqual(response.service_data.max_length,0xabcd)

	def test_request_upload_success_lfid(self):
		request = self.conn.touserqueue.get(timeout=0.2)
		self.assertEqual(request, b"\x35\x00\x12\x12\x34\xFF")
		self.conn.fromuserqueue.put(b"\x75\x23\xab\xcd")	# Positive response

	def _test_request_upload_success_lfid(self):
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
		response = self.udsclient.request_upload(memory_location=memloc)
		self.assertEqual(response.service_data.max_length,0xabcd)

	def test_request_upload_success_dfi(self):
		request = self.conn.touserqueue.get(timeout=0.2)
		self.assertEqual(request, b"\x35\x52\x12\x12\x34\xFF")
		self.conn.fromuserqueue.put(b"\x75\x20\xab\xcd")	# Positive response

	def _test_request_upload_success_dfi(self):
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
		dfi  =DataFormatIdentifier(compression=5, encryption=2)
		response = self.udsclient.request_upload(memory_location=memloc, dfi=dfi)
		self.assertEqual(response.service_data.max_length,0xabcd)

	def test_incomplete_nblock_response_exception(self):
		self.wait_request_and_respond(b"\x75\x40\xab\xcd")	# Missing 2 bytes to complete number of block

	def _test_incomplete_nblock_response_exception(self):
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
		with self.assertRaises(InvalidResponseException):
			self.udsclient.request_upload(memory_location=memloc)

	def test_incomplete_nblock_response_no_exception(self):
		self.wait_request_and_respond(b"\x75\x40\xab\xcd")	# Missing 2 bytes to complete number of block

	def _test_incomplete_nblock_response_no_exception(self):
		self.udsclient.config['exception_on_invalid_response'] = False	
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
		response = self.udsclient.request_upload(memory_location=memloc)
		self.assertFalse(response.valid)

	def test_request_upload_invalidservice_exception(self):
		self.wait_request_and_respond(b"\x00\x20\x12\x34") #Inexistent Service

	def _test_request_upload_invalidservice_exception(self):
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
		with self.assertRaises(InvalidResponseException) as handle:
			self.udsclient.request_upload(memory_location=memloc)

	def test_request_upload_invalidservice_no_exception(self):
		self.wait_request_and_respond(b"\x00\x20\x12\x34") #Inexistent Service

	def _test_request_upload_invalidservice_no_exception(self):
		self.udsclient.config['exception_on_invalid_response'] = False	
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
		response = self.udsclient.request_upload(memory_location=memloc)
		self.assertFalse(response.valid)

	def test_request_upload_wrongservice_exception(self):
		self.wait_request_and_respond(b"\x7E\x20\x12\x34") # Valid but wrong service (Tester Present)

	def _test_request_upload_wrongservice_exception(self):
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
		with self.assertRaises(UnexpectedResponseException) as handle:
			self.udsclient.request_upload(memory_location=memloc)

	def test_request_upload_wrongservice_no_exception(self):
		self.wait_request_and_respond(b"\x7E\x20\x12\x34") # Valid but wrong service (Tester Present)

	def _test_request_upload_wrongservice_no_exception(self):
		self.udsclient.config['exception_on_unexpected_response'] = False
		memloc = MemoryLocation(address=0x1234, memorysize=0xFF, address_format=16, memorysize_format=8)
		response = self.udsclient.request_upload(memory_location=memloc)
		self.assertTrue(response.valid)
		self.assertTrue(response.unexpected)

	def test_bad_params(self):
		pass

	def _test_bad_params(self):
		with self.assertRaises(ValueError) as handle:
			self.udsclient.request_upload(memory_location=1)
		
		with self.assertRaises(ValueError) as handle:
			self.udsclient.request_upload(memory_location="asd")
