Used StreamChunker for clipboard and file transfer #4601

Clipboard is not handled at this point
This commit is contained in:
Jerry (Xinyu Hou) 2015-05-19 09:30:35 -07:00
parent 70be9cd97f
commit c674642181
15 changed files with 410 additions and 64 deletions

View File

@ -22,6 +22,7 @@
#include "client/ServerProxy.h" #include "client/ServerProxy.h"
#include "synergy/Screen.h" #include "synergy/Screen.h"
#include "synergy/Clipboard.h" #include "synergy/Clipboard.h"
#include "synergy/FileChunk.h"
#include "synergy/DropHelper.h" #include "synergy/DropHelper.h"
#include "synergy/PacketStreamFilter.h" #include "synergy/PacketStreamFilter.h"
#include "synergy/ProtocolUtil.h" #include "synergy/ProtocolUtil.h"
@ -422,12 +423,12 @@ Client::sendConnectionFailedEvent(const char* msg)
void void
Client::sendFileChunk(const void* data) Client::sendFileChunk(const void* data)
{ {
StreamChunker::Chunk* chunk = reinterpret_cast<StreamChunker::Chunk*>(const_cast<void*>(data)); FileChunk* chunk = reinterpret_cast<FileChunk*>(const_cast<void*>(data));
LOG((CLOG_DEBUG1 "send file chunk")); LOG((CLOG_DEBUG1 "send file chunk"));
assert(m_server != NULL); assert(m_server != NULL);
// relay // relay
m_server->fileChunkSending(chunk->m_chunk[0], &(chunk->m_chunk[1]), chunk->m_size); m_server->fileChunkSending(chunk->m_chunk[0], &chunk->m_chunk[1], chunk->m_dataSize);
} }
void void
@ -821,7 +822,7 @@ Client::sendFileThread(void* filename)
{ {
try { try {
char* name = reinterpret_cast<char*>(filename); char* name = reinterpret_cast<char*>(filename);
StreamChunker::sendFileChunks(name, m_events, this); StreamChunker::sendFile(name, m_events, this);
} }
catch (std::runtime_error error) { catch (std::runtime_error error) {
LOG((CLOG_ERR "failed sending file chunks: %s", error.what())); LOG((CLOG_ERR "failed sending file chunks: %s", error.what()));

View File

@ -19,7 +19,6 @@
#include "server/Server.h" #include "server/Server.h"
#include "synergy/StreamChunker.h" #include "synergy/StreamChunker.h"
#include "synergy/ProtocolUtil.h"
#include "io/IStream.h" #include "io/IStream.h"
#include "base/Log.h" #include "base/Log.h"
@ -37,6 +36,20 @@ ClientProxy1_6::~ClientProxy1_6()
{ {
} }
bool
ClientProxy1_6::parseMessage(const UInt8* code)
{
//TODO:: parse data tansfer
if (memcmp(code, kMsgDFileTransfer, 4) == 0) {
fileChunkReceived();
}
else {
return ClientProxy1_5::parseMessage(code);
}
return true;
}
void void
ClientProxy1_6::setClipboard(ClipboardID id, const IClipboard* clipboard) ClientProxy1_6::setClipboard(ClipboardID id, const IClipboard* clipboard)
{ {
@ -51,6 +64,6 @@ ClientProxy1_6::setClipboard(ClipboardID id, const IClipboard* clipboard)
size_t size = data.size(); size_t size = data.size();
LOG((CLOG_DEBUG "sending clipboard %d to \"%s\" size=%d", id, getName().c_str(), size)); LOG((CLOG_DEBUG "sending clipboard %d to \"%s\" size=%d", id, getName().c_str(), size));
StreamChunker::sendData(data, size, id, m_events, this); StreamChunker::sendClipboard(data, size, id, 0, m_events, this);
} }
} }

View File

@ -28,6 +28,7 @@ public:
ClientProxy1_6(const String& name, synergy::IStream* adoptedStream, Server* server, IEventQueue* events); ClientProxy1_6(const String& name, synergy::IStream* adoptedStream, Server* server, IEventQueue* events);
~ClientProxy1_6(); ~ClientProxy1_6();
virtual bool parseMessage(const UInt8* code);
virtual void setClipboard(ClipboardID id, const IClipboard* clipboard); virtual void setClipboard(ClipboardID id, const IClipboard* clipboard);
private: private:

View File

@ -25,6 +25,7 @@
#include "server/ClientProxy1_3.h" #include "server/ClientProxy1_3.h"
#include "server/ClientProxy1_4.h" #include "server/ClientProxy1_4.h"
#include "server/ClientProxy1_5.h" #include "server/ClientProxy1_5.h"
#include "server/ClientProxy1_6.h"
#include "synergy/protocol_types.h" #include "synergy/protocol_types.h"
#include "synergy/ProtocolUtil.h" #include "synergy/ProtocolUtil.h"
#include "synergy/XSynergy.h" #include "synergy/XSynergy.h"
@ -227,6 +228,10 @@ ClientProxyUnknown::handleData(const Event&, void*)
case 5: case 5:
m_proxy = new ClientProxy1_5(name, m_stream, m_server, m_events); m_proxy = new ClientProxy1_5(name, m_stream, m_server, m_events);
break; break;
case 6:
m_proxy = new ClientProxy1_6(name, m_stream, m_server, m_events);
break;
} }
} }

View File

@ -22,13 +22,14 @@
#include "server/ClientProxyUnknown.h" #include "server/ClientProxyUnknown.h"
#include "server/PrimaryClient.h" #include "server/PrimaryClient.h"
#include "server/ClientListener.h" #include "server/ClientListener.h"
#include "synergy/FileChunk.h"
#include "synergy/IPlatformScreen.h" #include "synergy/IPlatformScreen.h"
#include "synergy/DropHelper.h" #include "synergy/DropHelper.h"
#include "synergy/option_types.h" #include "synergy/option_types.h"
#include "synergy/protocol_types.h" #include "synergy/protocol_types.h"
#include "synergy/XScreen.h" #include "synergy/XScreen.h"
#include "synergy/XSynergy.h" #include "synergy/XSynergy.h"
#include "synergy/FileChunker.h" #include "synergy/StreamChunker.h"
#include "synergy/KeyState.h" #include "synergy/KeyState.h"
#include "synergy/Screen.h" #include "synergy/Screen.h"
#include "synergy/PacketStreamFilter.h" #include "synergy/PacketStreamFilter.h"
@ -508,7 +509,7 @@ Server::switchScreen(BaseClientProxy* dst,
// send the clipboard data to new active screen // send the clipboard data to new active screen
m_dataTransmissionThread = new Thread( m_dataTransmissionThread = new Thread(
new TMethodJob<Server>( new TMethodJob<Server>(
this, &Server::clipboardTransmissionThread, this, &Server::sendClipboardThread,
NULL)); NULL));
Server::SwitchToScreenInfo* info = Server::SwitchToScreenInfo* info =
@ -1852,7 +1853,7 @@ Server::sendDragInfo(BaseClientProxy* newScreen)
} }
void void
Server::clipboardTransmissionThread(void*) Server::sendClipboardThread(void*)
{ {
for (ClipboardID id = 0; id < kClipboardEnd; ++id) { for (ClipboardID id = 0; id < kClipboardEnd; ++id) {
m_active->setClipboard(id, &m_clipboards[id].m_clipboard); m_active->setClipboard(id, &m_clipboards[id].m_clipboard);
@ -2033,13 +2034,13 @@ Server::onMouseWheel(SInt32 xDelta, SInt32 yDelta)
void void
Server::onFileChunkSending(const void* data) Server::onFileChunkSending(const void* data)
{ {
StreamChunker::Chunk* chunk = reinterpret_cast<StreamChunker::Chunk*>(const_cast<void*>(data)); FileChunk* chunk = reinterpret_cast<FileChunk*>(const_cast<void*>(data));
LOG((CLOG_DEBUG1 "sending file chunk")); LOG((CLOG_DEBUG1 "sending file chunk"));
assert(m_active != NULL); assert(m_active != NULL);
// relay // relay
m_active->fileChunkSending(chunk->m_chunk[0], &(chunk->m_chunk[1]), chunk->m_size); m_active->fileChunkSending(chunk->m_chunk[0], &chunk->m_chunk[1], chunk->m_dataSize);
} }
void void
@ -2376,7 +2377,7 @@ Server::sendFileThread(void* data)
try { try {
char* filename = reinterpret_cast<char*>(data); char* filename = reinterpret_cast<char*>(data);
LOG((CLOG_DEBUG "sending file to client, filename=%s", filename)); LOG((CLOG_DEBUG "sending file to client, filename=%s", filename));
StreamChunker::sendFileChunks(filename, m_events, this); StreamChunker::sendFile(filename, m_events, this);
} }
catch (std::runtime_error error) { catch (std::runtime_error error) {
LOG((CLOG_ERR "failed sending file chunks, error: %s", error.what())); LOG((CLOG_ERR "failed sending file chunks, error: %s", error.what()));

View File

@ -371,7 +371,7 @@ private:
void sendDragInfo(BaseClientProxy* newScreen); void sendDragInfo(BaseClientProxy* newScreen);
// thread funciton for sending clipboard // thread funciton for sending clipboard
void clipboardTransmissionThread(void*); void sendClipboardThread(void*);
public: public:
bool m_mock; bool m_mock;

30
src/lib/synergy/Chunk.cpp Normal file
View File

@ -0,0 +1,30 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/Chunk.h"
#include "base/String.h"
Chunk::Chunk(size_t size)
{
m_chunk = new char[size];
memset(m_chunk, 0, size);
}
Chunk::~Chunk()
{
delete[] m_chunk;
}

30
src/lib/synergy/Chunk.h Normal file
View File

@ -0,0 +1,30 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/basic_types.h"
class Chunk {
public:
Chunk(size_t size);
~Chunk();
public:
size_t m_dataSize;
char* m_chunk;
};

View File

@ -0,0 +1,81 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ClipboardChunk.h"
#include "synergy/protocol_types.h"
ClipboardChunk::ClipboardChunk(size_t size) :
Chunk(size)
{
m_dataSize = size - CLIPBOARD_CHUNK_META_SIZE;
}
ClipboardChunk*
ClipboardChunk::start(
ClipboardID id,
UInt32 sequence,
const String& size)
{
size_t sizeLength = size.size();
ClipboardChunk* start = new ClipboardChunk(sizeLength + CLIPBOARD_CHUNK_META_SIZE);
char* chunk = start->m_chunk;
chunk[0] = id;
UInt32* seq = reinterpret_cast<UInt32*>(&chunk[1]);
*seq = sequence;
chunk[5] = kDataStart;
memcpy(&chunk[6], size.c_str(), sizeLength);
chunk[sizeLength + CLIPBOARD_CHUNK_META_SIZE - 1] = '\0';
return start;
}
ClipboardChunk*
ClipboardChunk::data(
ClipboardID id,
UInt32 sequence,
const String& data)
{
size_t dataSize = data.size();
ClipboardChunk* chunk = new ClipboardChunk(dataSize + CLIPBOARD_CHUNK_META_SIZE);
char* chunkData = chunk->m_chunk;
chunkData[0] = id;
UInt32* seq = reinterpret_cast<UInt32*>(&chunkData[1]);
*seq = sequence;
chunkData[5] = kDataChunk;
memcpy(&chunkData[6], data.c_str(), dataSize);
chunkData[dataSize + CLIPBOARD_CHUNK_META_SIZE - 1] = '\0';
return chunk;
}
ClipboardChunk*
ClipboardChunk::end(ClipboardID id, UInt32 sequence)
{
ClipboardChunk* end = new ClipboardChunk(CLIPBOARD_CHUNK_META_SIZE);
char* chunk = end->m_chunk;
chunk[0] = id;
UInt32* seq = reinterpret_cast<UInt32*>(&chunk[1]);
*seq = sequence;
chunk[5] = kDataEnd;
chunk[CLIPBOARD_CHUNK_META_SIZE - 1] = '\0';
return end;
}

View File

@ -0,0 +1,40 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "synergy/Chunk.h"
#include "synergy/clipboard_types.h"
#include "base/String.h"
#include "common/basic_types.h"
#define CLIPBOARD_CHUNK_META_SIZE 7
class ClipboardChunk : public Chunk {
public:
ClipboardChunk(size_t size);
static ClipboardChunk* start(
ClipboardID id,
UInt32 sequence,
const String& size);
static ClipboardChunk* data(
ClipboardID id,
UInt32 sequence,
const String& data);
static ClipboardChunk* end(ClipboardID id, UInt32 sequence);
};

View File

@ -0,0 +1,62 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/FileChunk.h"
#include "synergy/protocol_types.h"
FileChunk::FileChunk(size_t size) :
Chunk(size)
{
m_dataSize = size - FILE_CHUNK_META_SIZE;
}
FileChunk*
FileChunk::start(const String& size)
{
size_t sizeLength = size.size();
FileChunk* start = new FileChunk(sizeLength + FILE_CHUNK_META_SIZE);
char* chunk = start->m_chunk;
chunk[0] = kDataStart;
memcpy(&chunk[1], size.c_str(), sizeLength);
chunk[sizeLength + 1] = '\0';
return start;
}
FileChunk*
FileChunk::data(UInt8* data, size_t dataSize)
{
FileChunk* chunk = new FileChunk(dataSize + FILE_CHUNK_META_SIZE);
char* chunkData = chunk->m_chunk;
chunkData[0] = kDataChunk;
memcpy(&chunkData[1], data, dataSize);
chunkData[dataSize + 1] = '\0';
return chunk;
}
FileChunk*
FileChunk::end()
{
FileChunk* end = new FileChunk(FILE_CHUNK_META_SIZE);
char* chunk = end->m_chunk;
chunk[0] = kDataEnd;
chunk[1] = '\0';
return end;
}

View File

@ -0,0 +1,33 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "synergy/Chunk.h"
#include "base/String.h"
#include "common/basic_types.h"
#define FILE_CHUNK_META_SIZE 2
class FileChunk : public Chunk {
public:
FileChunk(size_t size);
static FileChunk* start(const String& size);
static FileChunk* data(UInt8* data, size_t dataSize);
static FileChunk* end();
};

View File

@ -17,29 +17,24 @@
#pragma once #pragma once
#include "synergy/clipboard_types.h"
#include "base/String.h" #include "base/String.h"
class IEventQueue; class IEventQueue;
class StreamChunker { class StreamChunker {
public: public:
//! FileChunk data static void sendFile(
class Chunk { char* filename,
public: IEventQueue* events,
Chunk(size_t size) : m_size(size - 2) void* eventTarget);
{ static void sendClipboard(
m_chunk = new char[size]; String& data,
} size_t size,
ClipboardID id,
~Chunk() { delete[] m_chunk; } UInt32 sequence,
IEventQueue* events,
public: void* eventTarget);
const size_t m_size;
char* m_chunk;
};
static void sendFileChunks(char* filename, IEventQueue* events, void* eventTarget);
static String intToString(size_t i);
private: private:
static const size_t m_chunkSize; static const size_t m_chunkSize;

View File

@ -28,6 +28,7 @@
#include "server/Server.h" #include "server/Server.h"
#include "server/ClientListener.h" #include "server/ClientListener.h"
#include "client/Client.h" #include "client/Client.h"
#include "synergy/FileChunk.h"
#include "synergy/StreamChunker.h" #include "synergy/StreamChunker.h"
#include "net/SocketMultiplexer.h" #include "net/SocketMultiplexer.h"
#include "net/NetworkAddress.h" #include "net/NetworkAddress.h"
@ -60,7 +61,6 @@ const size_t kMockFileSize = 1024 * 1024 * 10; // 10MB
void getScreenShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h); void getScreenShape(SInt32& x, SInt32& y, SInt32& w, SInt32& h);
void getCursorPos(SInt32& x, SInt32& y); void getCursorPos(SInt32& x, SInt32& y);
String intToString(size_t i);
UInt8* newMockData(size_t size); UInt8* newMockData(size_t size);
void createFile(fstream& file, const char* filename, size_t size); void createFile(fstream& file, const char* filename, size_t size);
@ -415,38 +415,28 @@ void
NetworkTests::sendMockData(void* eventTarget) NetworkTests::sendMockData(void* eventTarget)
{ {
// send first message (file size) // send first message (file size)
String size = intToString(kMockDataSize); String size = synergy::string::intToString(kMockDataSize);
size_t sizeLength = size.size(); FileChunk* sizeMessage = FileChunk::start(size);
StreamChunker::Chunk* sizeMessage = new StreamChunker::Chunk(sizeLength + 2);
char* chunkData = sizeMessage->m_chunk;
chunkData[0] = kDataStart;
memcpy(&chunkData[1], size.c_str(), sizeLength);
chunkData[sizeLength + 1] = '\0';
m_events.addEvent(Event(m_events.forIScreen().fileChunkSending(), eventTarget, sizeMessage)); m_events.addEvent(Event(m_events.forIScreen().fileChunkSending(), eventTarget, sizeMessage));
// send chunk messages with incrementing chunk size // send chunk messages with incrementing chunk size
size_t lastSize = 0; size_t lastSize = 0;
size_t sentLength = 0; size_t sentLength = 0;
while (true) { while (true) {
size_t chunkSize = lastSize + kMockDataChunkIncrement; size_t dataSize = lastSize + kMockDataChunkIncrement;
// make sure we don't read too much from the mock data. // make sure we don't read too much from the mock data.
if (sentLength + chunkSize > kMockDataSize) { if (sentLength + dataSize > kMockDataSize) {
chunkSize = kMockDataSize - sentLength; dataSize = kMockDataSize - sentLength;
} }
// first byte is the chunk mark, last is \0 // first byte is the chunk mark, last is \0
StreamChunker::Chunk* fileChunk = new StreamChunker::Chunk(chunkSize + 2); FileChunk* chunk = FileChunk::data(m_mockData, dataSize);
char* chunkData = fileChunk->m_chunk; m_events.addEvent(Event(m_events.forIScreen().fileChunkSending(), eventTarget, chunk));
chunkData[0] = kDataChunk; sentLength += dataSize;
memcpy(&chunkData[1], &m_mockData[sentLength], chunkSize); lastSize = dataSize;
chunkData[chunkSize + 1] = '\0';
m_events.addEvent(Event(m_events.forIScreen().fileChunkSending(), eventTarget, fileChunk));
sentLength += chunkSize;
lastSize = chunkSize;
if (sentLength == kMockDataSize) { if (sentLength == kMockDataSize) {
break; break;
@ -455,11 +445,7 @@ NetworkTests::sendMockData(void* eventTarget)
} }
// send last message // send last message
StreamChunker::Chunk* transferFinished = new StreamChunker::Chunk(2); FileChunk* transferFinished = FileChunk::end();
chunkData = transferFinished->m_chunk;
chunkData[0] = kDataEnd;
chunkData[1] = '\0';
m_events.addEvent(Event(m_events.forIScreen().fileChunkSending(), eventTarget, transferFinished)); m_events.addEvent(Event(m_events.forIScreen().fileChunkSending(), eventTarget, transferFinished));
} }
@ -527,12 +513,4 @@ getCursorPos(SInt32& x, SInt32& y)
y = 0; y = 0;
} }
String
intToString(size_t i)
{
stringstream ss;
ss << i;
return ss.str();
}
#endif // WINAPI_CARBON #endif // WINAPI_CARBON

View File

@ -0,0 +1,76 @@
/*
* synergy -- mouse and keyboard sharing utility
* Copyright (C) 2015 Synergy Si Inc.
*
* This package is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* found in the file LICENSE that should have accompanied this file.
*
* This package is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "synergy/ClipboardChunk.h"
#include "synergy/protocol_types.h"
#include "test/global/gtest.h"
TEST(ClipboardChunkTests, start_formatStartChunk)
{
ClipboardID id = 0;
UInt32 sequence = 0;
String mockDataSize("10");
ClipboardChunk* chunk = ClipboardChunk::start(id, sequence, mockDataSize);
EXPECT_EQ(id, chunk->m_chunk[0]);
EXPECT_EQ(sequence, (UInt32)chunk->m_chunk[1]);
EXPECT_EQ(kDataStart, chunk->m_chunk[5]);
EXPECT_EQ('1', chunk->m_chunk[6]);
EXPECT_EQ('0', chunk->m_chunk[7]);
EXPECT_EQ('\0', chunk->m_chunk[8]);
delete chunk;
}
TEST(ClipboardChunkTests, data_formatDataChunk)
{
ClipboardID id = 0;
UInt32 sequence = 1;
String mockData("mock data");
ClipboardChunk* chunk = ClipboardChunk::data(id, sequence, mockData);
EXPECT_EQ(id, chunk->m_chunk[0]);
EXPECT_EQ(sequence, (UInt32)chunk->m_chunk[1]);
EXPECT_EQ(kDataChunk, chunk->m_chunk[5]);
EXPECT_EQ('m', chunk->m_chunk[6]);
EXPECT_EQ('o', chunk->m_chunk[7]);
EXPECT_EQ('c', chunk->m_chunk[8]);
EXPECT_EQ('k', chunk->m_chunk[9]);
EXPECT_EQ(' ', chunk->m_chunk[10]);
EXPECT_EQ('d', chunk->m_chunk[11]);
EXPECT_EQ('a', chunk->m_chunk[12]);
EXPECT_EQ('t', chunk->m_chunk[13]);
EXPECT_EQ('a', chunk->m_chunk[14]);
EXPECT_EQ('\0', chunk->m_chunk[15]);
delete chunk;
}
TEST(ClipboardChunkTests, end_formatDataChunk)
{
ClipboardID id = 1;
UInt32 sequence = 1;
ClipboardChunk* chunk = ClipboardChunk::end(id, sequence);
EXPECT_EQ(id, chunk->m_chunk[0]);
EXPECT_EQ(sequence, (UInt32)chunk->m_chunk[1]);
EXPECT_EQ(kDataEnd, chunk->m_chunk[5]);
EXPECT_EQ('\0', chunk->m_chunk[6]);
delete chunk;
}