예제 #1
0
/// @brief Tests for correct reponse to an Open command on a file, followed by Terminate
bool MavlinkFtpTest::_open_terminate_test(void)
{
	MavlinkFTP::PayloadHeader		payload;
	mavlink_file_transfer_protocol_t	ftp_msg;
	MavlinkFTP::PayloadHeader		*reply;
	
	for (size_t i=0; i<sizeof(_rgReadTestCases)/sizeof(_rgReadTestCases[0]); i++) {
		struct stat st;
		const ReadTestCase *test = &_rgReadTestCases[i];
		
		payload.opcode = MavlinkFTP::kCmdOpenFileRO;
		payload.offset = 0;
		
		bool success = _send_receive_msg(&payload,		// FTP payload header
						 strlen(test->file)+1,	// size in bytes of data
						 (uint8_t*)test->file,	// Data to start into FTP message payload
						 &ftp_msg,		// Response from server
						 &reply);		// Payload inside FTP message response
		if (!success) {
			return false;
		}
		
		ut_compare("stat failed", stat(test->file, &st), 0);
		
		
		ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
		ut_compare("Incorrect payload size", reply->size, sizeof(uint32_t));
		ut_compare("File size incorrect", *((uint32_t*)&reply->data[0]), (uint32_t)st.st_size);

		payload.opcode = MavlinkFTP::kCmdTerminateSession;
		payload.session = reply->session;
		payload.size = 0;
		
		success = _send_receive_msg(&payload,	// FTP payload header
					    0,		// size in bytes of data
					    nullptr,	// Data to start into FTP message payload
					    &ftp_msg,	// Response from server
					    &reply);	// Payload inside FTP message response
		if (!success) {
			return false;
		}
		
		ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
		ut_compare("Incorrect payload size", reply->size, 0);
	}

	return true;
}
예제 #2
0
/// @brief Tests for correct reponse to a List command on a valid directory, but with an offset that
/// is beyond the last directory entry.
bool MavlinkFtpTest::_list_eof_test(void)
{
	MavlinkFTP::PayloadHeader		payload;
	mavlink_file_transfer_protocol_t	ftp_msg;
	MavlinkFTP::PayloadHeader		*reply;
	const char				*dir = "/";
	
	payload.opcode = MavlinkFTP::kCmdListDirectory;
	payload.offset = 4;	// offset past top level dirs
	
	bool success = _send_receive_msg(&payload,	// FTP payload header
					strlen(dir)+1,	// size in bytes of data
					(uint8_t*)dir,	// Data to start into FTP message payload
					&ftp_msg,	// Response from server
					&reply);	// Payload inside FTP message response
	if (!success) {
		return false;
	}

	ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
	ut_compare("Incorrect payload size", reply->size, 1);
	ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrEOF);
	
	return true;
}
예제 #3
0
/// @brief Tests for correct reponse to an Open command on a file which does not exist.
bool MavlinkFtpTest::_open_badfile_test(void)
{
	MavlinkFTP::PayloadHeader		payload;
	mavlink_file_transfer_protocol_t	ftp_msg;
	MavlinkFTP::PayloadHeader		*reply;
	const char				*dir = "/foo";	// non-existent file
	
	payload.opcode = MavlinkFTP::kCmdOpenFileRO;
	payload.offset = 0;
	
	bool success = _send_receive_msg(&payload,	// FTP payload header
					strlen(dir)+1,	// size in bytes of data
					(uint8_t*)dir,	// Data to start into FTP message payload
					&ftp_msg,	// Response from server
					&reply);	// Payload inside FTP message response
	if (!success) {
		return false;
	}
	
	ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
	ut_compare("Incorrect payload size", reply->size, 2);
	ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrFailErrno);
	
	return true;
}
예제 #4
0
bool MavlinkFtpTest::_removedirectory_test(void)
{
	MavlinkFTP::PayloadHeader		payload;
	mavlink_file_transfer_protocol_t	ftp_msg;
	MavlinkFTP::PayloadHeader		*reply;
	int					fd;
	
	struct _testCase {
		const char	*dir;
		bool		success;
		bool		deleteFile;
	};
	static const struct _testCase rgTestCases[] = {
		{ "/bogus",						false,	false },
		{ "/etc/unit_test_data/mavlink_tests/empty_dir",	false,	false },
		{ _unittest_microsd_dir,				false,	false },
		{ _unittest_microsd_file,				false,	false },
		{ _unittest_microsd_dir,				true,	true },
	};
	
	ut_compare("mkdir failed", ::mkdir(_unittest_microsd_dir, S_IRWXU | S_IRWXG | S_IRWXO), 0);
	ut_assert("open failed", (fd = ::open(_unittest_microsd_file, O_CREAT | O_EXCL)) != -1);
	::close(fd);
	
	for (size_t i=0; i<sizeof(rgTestCases)/sizeof(rgTestCases[0]); i++) {
		const struct _testCase *test = &rgTestCases[i];
		
		if (test->deleteFile) {
			ut_compare("unlink failed", ::unlink(_unittest_microsd_file), 0);
		}
		
		payload.opcode = MavlinkFTP::kCmdRemoveDirectory;
		payload.offset = 0;
		
		bool success = _send_receive_msg(&payload,		// FTP payload header
						 strlen(test->dir)+1,	// size in bytes of data
						 (uint8_t*)test->dir,	// Data to start into FTP message payload
						 &ftp_msg,		// Response from server
						 &reply);		// Payload inside FTP message response
		if (!success) {
			return false;
		}
		
		if (test->success) {
			ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
			ut_compare("Incorrect payload size", reply->size, 0);
		} else {
			ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
			ut_compare("Incorrect payload size", reply->size, 2);
			ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrFailErrno);
		}
	}
	
	return true;
}
예제 #5
0
bool MavlinkFtpTest::_removefile_test()
{
	MavlinkFTP::PayloadHeader		payload;
	const MavlinkFTP::PayloadHeader		*reply;
	int					fd;

	struct _testCase {
		const char	*file;
		bool		success;
	};
	static const struct _testCase rgTestCases[] = {
		{ "/bogus",			false },
#ifdef __PX4_NUTTX
		// file can actually be deleted on linux
		{ _rgDownloadTestCases[0].file,	false },
#endif /* __PX4_NUTTX */
		{ _unittest_microsd_dir,	false },
		{ _unittest_microsd_file,	true },
		{ _unittest_microsd_file,	false },
	};

	ut_compare("mkdir failed", ::mkdir(_unittest_microsd_dir, S_IRWXU | S_IRWXG | S_IRWXO), 0);
	ut_assert("open failed", (fd = ::open(_unittest_microsd_file, O_CREAT | O_EXCL, S_IRWXU | S_IRWXG | S_IRWXO)) != -1);
	::close(fd);

	for (size_t i = 0; i < sizeof(rgTestCases) / sizeof(rgTestCases[0]); i++) {
		const struct _testCase *test = &rgTestCases[i];

		payload.opcode = MavlinkFTP::kCmdRemoveFile;
		payload.offset = 0;

		bool success = _send_receive_msg(&payload,		// FTP payload header
						 strlen(test->file) + 1,	// size in bytes of data
						 (uint8_t *)test->file,	// Data to start into FTP message payload
						 &reply);		// Payload inside FTP message response

		if (!success) {
			return false;
		}

		if (test->success) {
			ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
			ut_compare("Incorrect payload size", reply->size, 0);

		} else {
			ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
			ut_compare("Incorrect payload size", reply->size, 2);
			ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrFailErrno);
		}
	}

	return true;
}
예제 #6
0
/// @brief Tests for correct reponse to a Read command on an invalid session.
bool MavlinkFtpTest::_read_badsession_test(void)
{
	MavlinkFTP::PayloadHeader		payload;
	mavlink_file_transfer_protocol_t	ftp_msg;
	MavlinkFTP::PayloadHeader		*reply;
	const char				*file = _rgReadTestCases[0].file;
	
	payload.opcode = MavlinkFTP::kCmdOpenFileRO;
	payload.offset = 0;
	
	bool success = _send_receive_msg(&payload,	// FTP payload header
					 strlen(file)+1,	// size in bytes of data
					 (uint8_t*)file,	// Data to start into FTP message payload
					 &ftp_msg,	// Response from server
					 &reply);	// Payload inside FTP message response
	if (!success) {
		return false;
	}
	
	ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
	
	payload.opcode = MavlinkFTP::kCmdReadFile;
	payload.session = reply->session + 1;	// Invalid session
	payload.offset = 0;
	
	success = _send_receive_msg(&payload,	// FTP payload header
				    0,		// size in bytes of data
				    nullptr,	// Data to start into FTP message payload
				    &ftp_msg,	// Response from server
				    &reply);	// Payload inside FTP message response
	if (!success) {
		return false;
	}
	
	ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
	ut_compare("Incorrect payload size", reply->size, 1);
	ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrInvalidSession);
	
	return true;
}
예제 #7
0
/// @brief Tests for correct reponse to a Terminate command on an invalid session.
bool MavlinkFtpTest::_terminate_badsession_test()
{
	MavlinkFTP::PayloadHeader		payload;
	const MavlinkFTP::PayloadHeader		*reply;
	const char				*file = _rgDownloadTestCases[0].file;

	payload.opcode = MavlinkFTP::kCmdOpenFileRO;
	payload.offset = 0;

	bool success = _send_receive_msg(&payload,	// FTP payload header
					 strlen(file) + 1,	// size in bytes of data
					 (uint8_t *)file,	// Data to start into FTP message payload
					 &reply);	// Payload inside FTP message response

	if (!success) {
		return false;
	}

	ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);

	payload.opcode = MavlinkFTP::kCmdTerminateSession;
	payload.session = reply->session + 1;
	payload.size = 0;

	success = _send_receive_msg(&payload,	// FTP payload header
				    0,		// size in bytes of data
				    nullptr,	// Data to start into FTP message payload
				    &reply);	// Payload inside FTP message response

	if (!success) {
		return false;
	}

	ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
	ut_compare("Incorrect payload size", reply->size, 1);
	ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrInvalidSession);

	return true;
}
예제 #8
0
bool MavlinkFtpTest::_createdirectory_test()
{
	MavlinkFTP::PayloadHeader		payload;
	const MavlinkFTP::PayloadHeader		*reply;

	struct _testCase {
		const char	*dir;
		bool		success;
		bool		fail_exists;
	};
	static const struct _testCase rgTestCases[] = {
		{ "/etc/bogus",			false, false },
		{ _unittest_microsd_dir,	true, false },
		{ _unittest_microsd_dir,	false, true },
		{ "/fs/microsd/bogus/bogus",	false, false },
	};

	for (size_t i = 0; i < sizeof(rgTestCases) / sizeof(rgTestCases[0]); i++) {
		const struct _testCase *test = &rgTestCases[i];

		payload.opcode = MavlinkFTP::kCmdCreateDirectory;
		payload.offset = 0;

		bool success = _send_receive_msg(&payload,		// FTP payload header
						 strlen(test->dir) + 1,	// size in bytes of data
						 (uint8_t *)test->dir,	// Data to start into FTP message payload
						 &reply);		// Payload inside FTP message response

		if (!success) {
			return false;
		}

		if (test->success) {
			ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
			ut_compare("Incorrect payload size", reply->size, 0);

		} else if (test->fail_exists) {
			ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
			ut_compare("Incorrect payload size", reply->size, 1);
			ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrFailFileExists);

		} else {
			ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
			ut_compare("Incorrect payload size", reply->size, 2);
			ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrFailErrno);
		}
	}

	return true;
}
예제 #9
0
/// @brief Tests for correct behavior of an Ack response.
bool MavlinkFtpTest::_ack_test()
{
	MavlinkFTP::PayloadHeader		payload;
	const MavlinkFTP::PayloadHeader		*reply;

	payload.opcode = MavlinkFTP::kCmdNone;

	bool success = _send_receive_msg(&payload,	// FTP payload header
					 0,		// size in bytes of data
					 nullptr,	// Data to start into FTP message payload
					 &reply);	// Payload inside FTP message response

	if (!success) {
		return false;
	}

	ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
	ut_compare("Incorrect payload size", reply->size, 0);

	return true;
}
예제 #10
0
/// @brief Tests for correct response to an invalid opcpde.
bool MavlinkFtpTest::_bad_opcode_test()
{
	MavlinkFTP::PayloadHeader		payload;
	const MavlinkFTP::PayloadHeader		*reply;

	payload.opcode = 0xFF;	// bogus opcode

	bool success = _send_receive_msg(&payload,	// FTP payload header
					 0,		// size in bytes of data
					 nullptr,	// Data to start into FTP message payload
					 &reply);	// Payload inside FTP message response

	if (!success) {
		return false;
	}

	ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
	ut_compare("Incorrect payload size", reply->size, 1);
	ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrUnknownCommand);

	return true;
}
예제 #11
0
/// @brief Tests for correct reponse to a Read command on an open session.
bool MavlinkFtpTest::_read_test(void)
{
	MavlinkFTP::PayloadHeader		payload;
	mavlink_file_transfer_protocol_t	ftp_msg;
	MavlinkFTP::PayloadHeader		*reply;
	
	for (size_t i=0; i<sizeof(_rgReadTestCases)/sizeof(_rgReadTestCases[0]); i++) {
		struct stat st;
		const ReadTestCase *test = &_rgReadTestCases[i];
		
		// Read in the file so we can compare it to what we get back
		ut_compare("stat failed", stat(test->file, &st), 0);
		uint8_t *bytes = new uint8_t[st.st_size];
		ut_assert("new failed", bytes != nullptr);
		int fd = ::open(test->file, O_RDONLY);
		ut_assert("open failed", fd != -1);
		int bytes_read = ::read(fd, bytes, st.st_size);
		ut_compare("read failed", bytes_read, st.st_size);
		::close(fd);
		
		// Test case data files are created for specific boundary conditions
		ut_compare("Test case data files are out of date", test->length, st.st_size);
		
		payload.opcode = MavlinkFTP::kCmdOpenFileRO;
		payload.offset = 0;
		
		bool success = _send_receive_msg(&payload,		// FTP payload header
						 strlen(test->file)+1,	// size in bytes of data
						 (uint8_t*)test->file,	// Data to start into FTP message payload
						 &ftp_msg,		// Response from server
						 &reply);		// Payload inside FTP message response
		if (!success) {
			return false;
		}
		
		ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
		
		payload.opcode = MavlinkFTP::kCmdReadFile;
		payload.session = reply->session;
		payload.offset = 0;
		
		success = _send_receive_msg(&payload,	// FTP payload header
					    0,		// size in bytes of data
					    nullptr,	// Data to start into FTP message payload
					    &ftp_msg,	// Response from server
					    &reply);	// Payload inside FTP message response
		if (!success) {
			return false;
		}
		
		ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
		ut_compare("Offset incorrect", reply->offset, 0);
		
		if (test->length <= MAVLINK_MSG_FILE_TRANSFER_PROTOCOL_FIELD_PAYLOAD_LEN - sizeof(MavlinkFTP::PayloadHeader)) {
			ut_compare("Payload size incorrect", reply->size, (uint32_t)st.st_size);
			ut_compare("File contents differ", memcmp(reply->data, bytes, st.st_size), 0);
		}
		
		payload.opcode = MavlinkFTP::kCmdTerminateSession;
		payload.session = reply->session;
		payload.size = 0;
		
		success = _send_receive_msg(&payload,	// FTP payload header
					    0,		// size in bytes of data
					    nullptr,	// Data to start into FTP message payload
					    &ftp_msg,	// Response from server
					    &reply);	// Payload inside FTP message response
		if (!success) {
			return false;
		}
		
		ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
		ut_compare("Incorrect payload size", reply->size, 0);
	}
	
	return true;
}
예제 #12
0
bool MavlinkFtpTest::_list_test(void)
{
	MavlinkFTP::PayloadHeader		payload;
	mavlink_file_transfer_protocol_t	ftp_msg;
	MavlinkFTP::PayloadHeader		*reply;
	
	char response1[] = "Dempty_dir|Ftest_238.data\t238|Ftest_239.data\t239|Ftest_240.data\t240";
	char response2[] = "Ddev|Detc|Dfs|Dobj";
	
	struct _testCase {
		const char	*dir;		///< Directory to run List command on
		char		*response;	///< Expected response entries from List command
		int		response_count;	///< Number of directories that should be returned
		bool		success;	///< true: List command should succeed, false: List command should fail
	};
	struct _testCase rgTestCases[] = {
		{ "/bogus",				nullptr,	0,	false },
		{ "/etc/unit_test_data/mavlink_tests",	response1,	4,	true },
		{ "/",					response2,	4,	true },
	};

	for (size_t i=0; i<sizeof(rgTestCases)/sizeof(rgTestCases[0]); i++) {
		const struct _testCase *test = &rgTestCases[i];
		
		payload.opcode = MavlinkFTP::kCmdListDirectory;
		payload.offset = 0;
		
		bool success = _send_receive_msg(&payload,		// FTP payload header
						strlen(test->dir)+1,	// size in bytes of data
						(uint8_t*)test->dir,	// Data to start into FTP message payload
						&ftp_msg,		// Response from server
						&reply);		// Payload inside FTP message response
		if (!success) {
			return false;
		}
		
		if (test->success) {
			ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
			ut_compare("Incorrect payload size", reply->size, strlen(test->response) + 1);
			
			// The return order of directories from the List command is not repeatable. So we can't do a direct comparison
			// to a hardcoded return result string.
			
			// Convert null terminators to seperator char so we can use strok to parse returned data
			for (uint8_t j=0; j<reply->size-1; j++) {
				if (reply->data[j] == 0) {
					reply->data[j] = '|';
				}
			}
			
			// Loop over returned directory entries trying to find then in the response list
			char *dir;
			int response_count = 0;
			dir = strtok((char *)&reply->data[0], "|");
			while (dir != nullptr) {
				ut_assert("Returned directory not found in expected response", strstr(test->response, dir));
				response_count++;
				dir = strtok(nullptr, "|");
			}
			
			ut_compare("Incorrect number of directory entires returned", test->response_count, response_count);
		} else {
			ut_compare("Didn't get Nak back", reply->opcode, MavlinkFTP::kRspNak);
			ut_compare("Incorrect payload size", reply->size, 2);
			ut_compare("Incorrect error code", reply->data[0], MavlinkFTP::kErrFailErrno);
		}
	}
	
	return true;
}
예제 #13
0
/// @brief Tests for correct reponse to a Read command on an open session.
bool MavlinkFtpTest::_burst_test()
{
	MavlinkFTP::PayloadHeader		payload;
	const MavlinkFTP::PayloadHeader		*reply;
	BurstInfo				burst_info;



	for (size_t i = 0; i < sizeof(_rgDownloadTestCases) / sizeof(_rgDownloadTestCases[0]); i++) {
		struct stat st;
		const DownloadTestCase *test = &_rgDownloadTestCases[i];

		// Read in the file so we can compare it to what we get back
		ut_compare("stat failed", stat(test->file, &st), 0);
		uint8_t *bytes = new uint8_t[st.st_size];
		ut_assert("new failed", bytes != nullptr);
		int fd = ::open(test->file, O_RDONLY);
		ut_assert("open failed", fd != -1);
		int bytes_read = ::read(fd, bytes, st.st_size);
		ut_compare("read failed", bytes_read, st.st_size);
		::close(fd);

		// Test case data files are created for specific boundary conditions
		ut_compare("Test case data files are out of date", test->length, st.st_size);

		payload.opcode = MavlinkFTP::kCmdOpenFileRO;
		payload.offset = 0;

		bool success = _send_receive_msg(&payload,		// FTP payload header
						 strlen(test->file) + 1,	// size in bytes of data
						 (uint8_t *)test->file,	// Data to start into FTP message payload
						 &reply);		// Payload inside FTP message response

		if (!success) {
			return false;
		}

		ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);

		// Setup for burst response handler
		burst_info.burst_state = burst_state_first_ack;
		burst_info.single_packet_file = test->singlePacketRead;
		burst_info.file_size = st.st_size;
		burst_info.file_bytes = bytes;
		burst_info.ftp_test_class = this;
		_ftp_server->set_unittest_worker(MavlinkFtpTest::receive_message_handler_burst, &burst_info);

		// Send the burst command, message response will be handled by _receive_message_handler_stream
		payload.opcode = MavlinkFTP::kCmdBurstReadFile;
		payload.session = reply->session;
		payload.offset = 0;

		mavlink_message_t msg;
		_setup_ftp_msg(&payload, 0, nullptr, &msg);
		_ftp_server->handle_message(&msg);

		// First packet is sent using stream mechanism, so we need to force it out ourselves
		hrt_abstime t = 0;
		_ftp_server->send(t);

		ut_compare("Incorrect sequence of messages", burst_info.burst_state, burst_state_complete);

		// Put back generic message handler
		_ftp_server->set_unittest_worker(MavlinkFtpTest::receive_message_handler_generic, this);

		// Terminate session
		payload.opcode = MavlinkFTP::kCmdTerminateSession;
		payload.session = reply->session;
		payload.size = 0;

		success = _send_receive_msg(&payload,	// FTP payload header
					    0,		// size in bytes of data
					    nullptr,	// Data to start into FTP message payload
					    &reply);	// Payload inside FTP message response

		if (!success) {
			return false;
		}

		ut_compare("Didn't get Ack back", reply->opcode, MavlinkFTP::kRspAck);
		ut_compare("Incorrect payload size", reply->size, 0);
	}

	return true;
}