[ncp-buffer] support for saving write position and overwriting content (#2010)

This commit adds new `InFrame` related methods to `NcpFrameBuffer` to
allow user to get/save current write position in an input frame being
written to the buffer. The saved position can later be used to
overwrite the previously added content (using `InFrameOverwrite()`) or
discard a portion of written data and move the write pointer back to
the saved position (using `InFrameReset()`).

The unit test for NCP buffer is also updated to add new test-cases
specific for the newly added methods.
This commit is contained in:
Abtin Keshavarzian
2017-07-19 09:06:14 -07:00
committed by Jonathan Hui
parent 4603e9907f
commit fa1041f705
3 changed files with 319 additions and 50 deletions
+83
View File
@@ -382,6 +382,89 @@ exit:
return error;
}
otError NcpFrameBuffer::InFrameGetPosition(WritePosition &aPosition) const
{
otError error = OT_ERROR_NONE;
VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);
aPosition.mPosition = mWriteSegmentTail;
aPosition.mSegmentHead = mWriteSegmentHead;
exit:
return error;
}
otError NcpFrameBuffer::InFrameOverwrite(const WritePosition &aPosition, const uint8_t *aDataBuffer,
uint16_t aDataBufferLength)
{
otError error = OT_ERROR_NONE;
uint8_t *bufPtr;
uint16_t segmentLength;
uint16_t distance;
VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(aPosition.mSegmentHead == mWriteSegmentHead, error = OT_ERROR_INVALID_ARGS);
// Ensure the overwrite does not go beyond current sgement tail.
segmentLength = GetDistance(mWriteSegmentHead, mWriteSegmentTail, mWriteDirection);
distance = GetDistance(mWriteSegmentHead, aPosition.mPosition, mWriteDirection);
VerifyOrExit(distance + aDataBufferLength <= segmentLength, error = OT_ERROR_INVALID_ARGS);
bufPtr = aPosition.mPosition;
while (aDataBufferLength > 0)
{
*bufPtr = *aDataBuffer;
aDataBuffer++;
aDataBufferLength--;
bufPtr = GetUpdatedBufPtr(bufPtr, 1, mWriteDirection);
}
exit:
return error;
}
uint16_t NcpFrameBuffer::InFrameGetDistance(const WritePosition &aPosition) const
{
uint16_t distance = 0;
uint16_t segmentLength;
uint16_t offset;
VerifyOrExit(mWriteDirection != kUnknown);
VerifyOrExit(aPosition.mSegmentHead == mWriteSegmentHead);
segmentLength = GetDistance(mWriteSegmentHead, mWriteSegmentTail, mWriteDirection);
offset = GetDistance(mWriteSegmentHead, aPosition.mPosition, mWriteDirection);
VerifyOrExit(offset < segmentLength);
distance = GetDistance(aPosition.mPosition, mWriteSegmentTail, mWriteDirection);
exit:
return distance;
}
otError NcpFrameBuffer::InFrameReset(const WritePosition &aPosition)
{
otError error = OT_ERROR_NONE;
uint16_t segmentLength;
uint16_t offset;
VerifyOrExit(mWriteDirection != kUnknown, error = OT_ERROR_INVALID_STATE);
VerifyOrExit(aPosition.mSegmentHead == mWriteSegmentHead, error = OT_ERROR_INVALID_ARGS);
segmentLength = GetDistance(mWriteSegmentHead, mWriteSegmentTail, mWriteDirection);
offset = GetDistance(mWriteSegmentHead, aPosition.mPosition, mWriteDirection);
VerifyOrExit(offset < segmentLength, error = OT_ERROR_INVALID_ARGS);
mWriteSegmentTail = aPosition.mPosition;
exit:
return error;
}
otError NcpFrameBuffer::InFrameEnd(void)
{
otMessage *message;
+143 -50
View File
@@ -44,9 +44,9 @@ namespace ot {
* This class implements a buffer/queue for storing NCP frames.
*
* A frame can consist of a sequence of data bytes and/or the content of an `otMessage` or a combination of the two.
* NcpFrameBuffer implements priority FIFO logic for storing and reading frames. Two priority levels of high and low
* `NcpFrameBuffer` implements priority FIFO logic for storing and reading frames. Two priority levels of high and low
* are supported. Within same priority level first-in-first-out order is preserved. High priority frames are read
* ahead of the low priority ones.
* ahead of any low priority ones.
*
*/
class NcpFrameBuffer
@@ -54,7 +54,7 @@ class NcpFrameBuffer
public:
/**
* Defines the priority of frame. High priority frames are read before low priority frames. Within same priority
* Defines the priority of a frame. High priority frames are read before low priority frames. Within same priority
* level FIFO order is preserved.
*
*/
@@ -65,17 +65,40 @@ public:
};
/**
* Defines the (abstract) frame tag type. Frame tags can be compared with one another using operator `==`.
* Defines the (abstract) frame tag type. The tag is a unique value (within currently queued frames) associated
* with a frame in the `NcpFrameBuffer`. Frame tags can be compared with one another using operator `==`.
*
*/
typedef const void *FrameTag;
/**
* Defines the tag to indicate an invalid tag (e.g., when there is no frame).
* Defines the tag value indicating an invalid tag (e.g., when there is no frame).
*
*/
static const FrameTag kInvalidTag;
/**
* Defines the structure to hold a write position for an input frame (frame being written).
*
* It should be considered as an opaque data structure to users of `NcpFrameBuffer`.
*
*/
struct WritePosition
{
public:
/**
* The constructor for a `WritePosition` object.
*
*/
WritePosition(void): mPosition(0), mSegmentHead(0) { }
private:
uint8_t *mPosition; //< Pointer into buffer corresponding to saved write position.
uint8_t *mSegmentHead; //< Pointer to segment head.
friend class NcpFrameBuffer;
};
/**
* Defines a function pointer callback which is invoked to inform a change in `NcpFrameBuffer` either when a new
* frame is added/written to `NcpFrameBuffer` or when a frame is removed from `NcpFrameBuffer`.
@@ -89,7 +112,7 @@ public:
typedef void (*BufferCallback)(void *aContext, FrameTag aTag, Priority aPriority, NcpFrameBuffer *aNcpFrameBuffer);
/**
* This constructor creates an NCP frame buffer.
* This constructor initializes an NCP frame buffer.
*
* @param[in] aBuffer A pointer to a buffer which will be used by NCP frame buffer.
* @param[in] aBufferLength The buffer size (in bytes).
@@ -104,7 +127,7 @@ public:
void Clear(void);
/**
* This method sets the `FrameAdded` callback and its context.
* This method sets the FrameAdded callback and its context.
*
* Subsequent calls to this method will overwrite the previous callback and its context.
*
@@ -115,7 +138,7 @@ public:
void SetFrameAddedCallback(BufferCallback aFrameAddedCallback, void *aFrameAddedContext);
/**
* This method sets the `FrameRemoved` callback and its context.
* This method sets the FrameRemoved callback and its context.
*
* Subsequent calls to this method will overwrite the previous callback and its context.
*
@@ -126,12 +149,12 @@ public:
void SetFrameRemovedCallback(BufferCallback aFrameRemovedCallback, void *aFrameRemovedContext);
/**
* This method begins a new input frame to be added/written to the frame buffer.
* This method begins a new input frame (InFrame) to be added/written to the frame buffer.
* If there is a previous frame being written (for which `InFrameEnd()` has not yet been called), calling
* `InFrameBegin()` will discard and clear the previous unfinished frame.
*
* @param[in] aPriority Priority level of new input frame.
* @param[in] aPriority Priority level of the new input frame.
*
* @retval OT_ERROR_NONE Successfully started a new frame.
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to start a new frame.
@@ -140,13 +163,13 @@ public:
otError InFrameBegin(Priority aPriority);
/**
* This method adds data to the current input frame being written.
* This method adds data to the current input frame.
*
* Before using this method `InFrameBegin()` must be called to start and prepare a new input frame. Otherwise, this
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
*
* If no buffer space is available, this method will discard and clear the current input frame being written before
* returning the error status `OT_ERROR_NO_BUFS`.
* If no buffer space is available, this method will discard and clear the current input frame and return the
* error status `OT_ERROR_NO_BUFS`.
*
* @param[in] aDataBuffer A pointer to data buffer.
* @param[in] aDataBufferLength The length of the data buffer.
@@ -159,12 +182,12 @@ public:
otError InFrameFeedData(const uint8_t *aDataBuffer, uint16_t aDataBufferLength);
/**
* This method adds a message to the current input frame being written.
* This method adds a message to the current input frame.
*
* Before using this method `InFrameBegin()` must be called to start and prepare a new input frame. Otherwise, this
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
*
* If no buffer space is available, this method will discard and clear the frame before returning error status
* If no buffer space is available, this method will discard and clear the frame and return error status
* `OT_ERROR_NO_BUFS`.
*
* In case of success, the passed-in message @p aMessage will be owned by the frame buffer instance and will be
@@ -173,23 +196,94 @@ public:
* @param[in] aMessage A message to be added to current frame.
*
* @retval OT_ERROR_NONE Successfully added the message to the frame.
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add message.
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add the message.
* @retval OT_ERROR_INVALID_STATE InFrameBegin() has not been called earlier to start the frame.
* @retval OT_ERROR_INVALID_ARGS If @p aMessage is NULL.
*
*/
otError InFrameFeedMessage(otMessage *aMessage);
/**
* This method gets the current write position in the input frame.
*
* The write position is returned in @p aPosition. The saved position can later be used to overwrite the frame
* content (using `InFrameOverwrite()`) or discard a portion of written frame and move the write pointer back to
* the saved position (using `InFrameReset()`).
*
* @param[out] aPosition A reference to a `WritePosition` to save the current write position.
*
* @retval OT_ERROR_NONE Successfully saved current write position in @p aPosition.
* @retval OT_ERROR_INVALID_STATE InFrameBegin() has not been called earlier to start the frame.
*
*/
otError InFrameGetPosition(WritePosition &aPosition) const;
/**
* This method overwrites the previously written content in the current input frame at a given write position.
*
* The write position @p aPostion must belong to the same input frame saved earlier with `InFrameGetPosition()`.
* This method does not allow writing beyond the current end of the input frame (i.e., it can only write over
* previously added content). If writing @p aDataBufferLength bytes from write position @p aPosition goes beyond
* the end, this method does not change the input frame and returns error status `OT_ERROR_INVALID_ARGS`.
* This method cannot be used if the input frame has an added `otMessage` (i.e., a previous call to
* `InFrameFeedMessage()`).
*
* @param[in] aPosition A reference to the write position.
* @param[in] aDataBuffer A pointer to data buffer.
* @param[in] aDataBufferLength The length of the data buffer.
*
* @retval OT_ERROR_NONE Successfully overwrote the data at the given write position.
* @retval OT_ERROR_INVALID_STATE No input frame (`InFrameBegin()` has not been called).
* @retval OT_ERROR_INVALID_ARGS The given write position is not valid (i.e., if it does not belong to same
* input frame), or the input frame has an added `otMessage`, or the write
* operation will go beyond the current end of the input frame.
*
*/
otError InFrameOverwrite(const WritePosition &aPosition, const uint8_t *aDataBuffer, uint16_t aDataBufferLength);
/**
* This method resets the write position of input frame back to a previously saved position. Any previously
* added content after the write position is discarded.
*
* The write position @p aPosition must belong to the same input frame saved earlier with `InFrameGetPosition()`.
* This method cannot be used if the input frame has an added `otMessage` (i.e., a previous call to
* `InFrameFeedMessage()`).
*
* @param[in] aPosition A reference to write position
*
* @retval OT_ERROR_NONE Successfully reset the write position of current input frame..
* @retval OT_ERROR_INVALID_STATE No input frame (`InFrameBegin()` has not been called).
* @retval OT_ERROR_INVALID_ARGS The given write position is not valid (does not belong to same input frame), or
* the input frame has an added `otMessage`.
*
*/
otError InFrameReset(const WritePosition &aPosition);
/**
* This method gets the distance (number of bytes) from a given saved position to current end of frame.
*
* The write position @p aPosition must belong to the same input frame saved earlier with `InFrameGetPosition()`.
* This method cannot be used if the input frame has an added `otMessage` (i.e., a previous call to
* `InFrameFeedMessage()`). In case of invalid argument, this method returns zero.
*
* @param[in] aPosition A reference to write position
*
* @returns The distance (number of bytes) from a write position to current end of frame, or zero for invalid
* arguments.
*
*/
uint16_t InFrameGetDistance(const WritePosition &aPosition) const;
/**
* This method finalizes/ends the current input frame being written to the buffer.
*
* Before using this method `InFrameBegin()` must be called to start and prepare a new input frame. Otherwise, this
* method does nothing and returns error status `OT_ERROR_INVALID_STATE`.
* If no buffer space is available, this method will discard and clear the frame before returning error status
*
* If no buffer space is available, this method will discard and clear the frame and return error status
* `OT_ERROR_NO_BUFS`.
*
* @retval OT_ERROR_NONE Successfully added the message to the frame.
* @retval OT_ERROR_NONE Successfully ended the input frame.
* @retval OT_ERROR_NO_BUFS Insufficient buffer space available to add message.
* @retval OT_ERROR_INVALID_STATE InFrameBegin() has not been called earlier to start the frame.
*
@@ -202,7 +296,7 @@ public:
* currently queued frames) associated with a frame in the `NcpFrameBuffer`. The tag can be used to identify the
* same frame when it is read and removed from the NcpBuffer. Tags can be compared using operator `==`.
*
* @returns The tag of last successfully written frame, or `kInvalidTag` if no frame is written so far.
* @returns The tag of the last successfully written frame, or `kInvalidTag` if no frame is written so far.
*/
FrameTag InFrameGetLastTag(void) const;
@@ -266,8 +360,8 @@ public:
* The NCP buffer maintains a read offset for the current output frame being read. This method attempts to read
* the given number of bytes (@p aDataBufferLength) from the current frame and copies the bytes into the given
* data buffer (@p aDataBuffer). It also moves the read offset forward accordingly. If there are fewer bytes
* remaining in current frame than the request @p aReadLength, the available bytes are read/copied. This methods
* returns the actual number of bytes read.
* remaining in current frame than the requested @p aReadLength, the available bytes are read/copied. This methods
* returns the number of bytes read from frame and copied into @p aDataBuffer.
*
* @param[in] aDataBuffer A pointer to a data buffer.
* @param[in] aReadLength Number of bytes to read.
@@ -286,7 +380,8 @@ public:
*
* When a frame is removed all its associated messages will be freed.
*
* If the remove operation is successful, this method will invoke the `FrameRemovedCallback` (if provided).
* If the remove operation is successful, this method will invoke the `FrameRemovedCallback` (if not NULL) before
* returning the success state.
*
* @retval OT_ERROR_NONE Successfully removed the front frame.
* @retval OT_ERROR_NOT_FOUND No frame available in NCP frame buffer to remove.
@@ -326,11 +421,11 @@ public:
private:
/*
* NcpFrameBuffer Implementation
* -----------------------------
* `NcpFrameBuffer` Implementation
* -------------------------------
*
* NcpFrameBuffer internally stores a frame as a sequence of data segments. Each segment stores a portion of frame.
* The data segments are stored in the the main buffer `mBuffer`. mBuffer is utilized as a circular buffer.
* `NcpFrameBuffer` internally stores a frame as a sequence of data segments. Each segment stores a portion of
* frame. The data segments are stored in the the main buffer `mBuffer`. `mBuffer` is utilized as a circular buffer.
* The content of messages (which are added using `InFrameFeedMessage()`) are not directly copied in the `mBuffer`
* but instead they are enqueued in a message queue `mMessageQueue`.
@@ -360,22 +455,22 @@ private:
*
* This frame is stored as two segments:
*
* - Segment #1 contains "HelloThere" with a header of `0xC00A` which shows that this segment contains 10 data
* bytes, and it starts a new frame, and also must includes an appended message from the message queue.
* - Segment #1 contains "HelloThere" with a header value `0xC00A` which shows that this segment contains 10
* data bytes, and it starts a new frame, and also includes an appended message from the message queue.
*
* - Segment #2 contains "Bye" with a header value of `0x0003` showing length of 3 and no appended message.
*
* +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
* | C0 | 0A | `H` | 'e' | 'l' | 'l' | 'o' | 'T' | 'h' | 'e' | 'r' | 'e' | 00 | 03 | 'B' | 'y' | 'e' |
* | C0 | 0A | 'H' | 'e' | 'l' | 'l' | 'o' | 'T' | 'h' | 'e' | 'r' | 'e' | 00 | 03 | 'B' | 'y' | 'e' |
* +-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
* \ / \ /
* Segment #1 Header Segment #2 Header
*
*
* NcpFrameBuffer uses the `mBuffer` as a circular/ring buffer. To support two frame priorities the buffer is
* divided in two high-priority and low-priority regions. The high priority frames are stored in buffer in backward
* direction while the low-priority frames use the buffer in forward direction. This model ensures the available
* buffer space is utilized efficiently between all frame types.
* `NcpFrameBuffer` uses the `mBuffer` as a circular/ring buffer. To support two frame priorities the buffer is
* divided into two high-priority and low-priority regions. The high priority frames are stored in buffer in
* backward direction while the low-priority frames use the buffer in forward direction. This model ensures the
* available buffer space is utilized efficiently between all frame types.
*
* mReadFrameStart[kPriorityLow]
* |
@@ -393,19 +488,19 @@ private:
*
*
*
* When frames are removed, if possible, the `mReadFrameStart` and `mWriteFrameStart` pointers of two priority
* When frames are removed, if possible, the `mReadFrameStart` and `mWriteFrameStart` pointers of the two priority
* levels are moved closer to avoid gaps.
*
* For an output frame (frame being read), NcpFrameBuffer maintains a `ReadState` along with a set of pointers
* into the buffer:
*
* mReadFrameStart[priority]: Start of current/front frame.
* mReadFrameStart[priority]: Start of the current/front frame.
* |
* | mReadSegmentHead: Start of current segment of active output frame.
* | mReadSegmentHead: Start of the current segment.
* | |
* | | mReadPointer: Pointer to next byte to read in current segment.
* | | mReadPointer: Pointer to the next byte to read.
* | | |
* | | | mReadSegmentTail: End of current segment.
* | | | mReadSegmentTail: End of the current segment.
* | | | |
* V V V V
* ---------+------------+--------------------------+------+----------------+-----------------------------------
@@ -421,16 +516,16 @@ private:
* Note that the diagram above shows the pointers for a low-priority frame (with pointers increasing in forward
* direction).
*
* The `ReadState` indicates the state of current output frame and its read offset (e.g., read offset is in middle
* of a segment or it is in an appended message, or we are done with entire frame).
* The `ReadState` indicates the state of current output frame and its read offset (e.g., if read offset is in
* middle of a segment or if it is is middle of an appended message, or if we are done with entire frame).
*
* For a input frame (frame being written), the following pointers are maintained:
* For an input frame (frame being written), the following pointers are maintained:
*
* mWriteFrameWrite[priority]: Start of current/next frame being written.
* mWriteFrameWrite[priority]: Start of the current/next frame being written.
* |
* | mWriteSegmentHead: Start of current segment of active input frame.
* | mWriteSegmentHead: Start of the current segment of the active input frame.
* | |
* | | mWriteSegmentTail: Pointer to next byte to write in current segment.
* | | mWriteSegmentTail: Pointer to the next byte to write.
* | | |
* | | |
* | | |
@@ -449,7 +544,7 @@ private:
enum
{
kReadByteAfterFrameHasEnded = 0, // Value returned by ReadByte() when frame has ended.
kMessageReadBufferSize = 16, // Size of message buffer array.
kMessageReadBufferSize = 16, // Size of message buffer array `mMessageBuffer`.
kUnknownFrameLength = 0xffff, // Value used when frame length is unknown.
kSegmentHeaderSize = 2, // Length of the segment header.
kSegmentHeaderLengthMask = 0x3fff, // Bit mask to get the length from the segment header
@@ -463,10 +558,10 @@ private:
enum ReadState
{
kReadStateNotActive, // No current prepared out frame.
kReadStateNotActive, // No current prepared output frame.
kReadStateInSegment, // In middle of a data segment while reading current frame.
kReadStateInMessage, // In middle of a message while reading current frame.
kReadStateDone, // Current (out) frame is read fully.
kReadStateDone, // Current output frame is read fully.
};
enum Direction
@@ -476,8 +571,6 @@ private:
kUnknown,
};
// Private methods
uint8_t * GetUpdatedBufPtr(uint8_t *aBufPtr, uint16_t aOffset, Direction aDirection) const;
uint16_t GetDistance(uint8_t *aStartPtr, uint8_t *aEndPtr, Direction aDirection) const;
+93
View File
@@ -55,6 +55,7 @@ static const uint8_t sOpenThreadText[] = "OpenThread Rocks";
static const uint8_t sHelloText[] = "Hello there!";
static const uint8_t sMottoText[] = "Think good thoughts, say good words, do good deeds!";
static const uint8_t sMysteryText[] = "4871(\\):|(3$}{4|/4/2%14(\\)";
static const uint8_t sHexText[] = "0123456789abcdef";
static otInstance *sInstance;
static MessagePool *sMessagePool;
@@ -373,6 +374,7 @@ void TestNcpFrameBuffer(void)
Message *message;
uint8_t readBuffer[16];
uint16_t readLen, readOffset;
NcpFrameBuffer::WritePosition pos1, pos2;
sInstance = testInitInstance();
sMessagePool = &sInstance->mIp6.mMessagePool;
@@ -798,6 +800,97 @@ void TestNcpFrameBuffer(void)
SuccessOrQuit(ncpBuffer.OutFrameRemove(), "OutFrameRemove() failed.");
printf(" -- PASS\n");
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
printf("\n Test 14: Test InFrameOverwrite ");
printf("\nIterations: ");
for (j = 0; j < kTestIterationAttemps; j++)
{
uint16_t index;
bool addExtra = ((j % 7) != 0);
NcpFrameBuffer::Priority priority;
printf("*");
priority = ((j % 3) == 0) ? NcpFrameBuffer::kPriorityHigh : NcpFrameBuffer::kPriorityLow;
index = static_cast<uint16_t>(j % sizeof(sHexText));
SuccessOrQuit(ncpBuffer.InFrameBegin(priority), "InFrameBegin() failed");
SuccessOrQuit(ncpBuffer.InFrameFeedData(sHexText, index), "InFrameFeedData() failed.");
SuccessOrQuit(ncpBuffer.InFrameGetPosition(pos1), "InFrameGetPosition() failed");
SuccessOrQuit(ncpBuffer.InFrameFeedData(sMysteryText, sizeof(sHexText) - index), "InFrameFeedData() failed.");
VerifyOrQuit(ncpBuffer.InFrameGetDistance(pos1) == sizeof(sHexText) - index , "InFrameGetDistance() failed");
if (addExtra)
{
SuccessOrQuit(ncpBuffer.InFrameFeedData(sHelloText, sizeof(sHelloText)), "InFrameFeedData() failed.");
}
SuccessOrQuit(ncpBuffer.InFrameOverwrite(pos1, sHexText + index, sizeof(sHexText) - index),
"InFrameOverwrite() failed.");
VerifyOrQuit(ncpBuffer.InFrameGetDistance(pos1) == sizeof(sHexText) - index + (addExtra ? sizeof(sHelloText) : 0),
"InFrameGetDistance() failed");
SuccessOrQuit(ncpBuffer.InFrameEnd(), "InFrameEnd() failed.");
VerifyOrQuit(ncpBuffer.InFrameGetPosition(pos2) == OT_ERROR_INVALID_STATE, "GetPosition failed.");
VerifyOrQuit(ncpBuffer.InFrameOverwrite(pos1, sHexText, 0) != OT_ERROR_NONE, "Failed to give error.");
SuccessOrQuit(ncpBuffer.OutFrameBegin(), "OutFrameBegin() failed");
ReadAndVerifyContent(ncpBuffer, sHexText, sizeof(sHexText));
if (addExtra)
{
ReadAndVerifyContent(ncpBuffer, sHelloText, sizeof(sHelloText));
}
SuccessOrQuit(ncpBuffer.OutFrameRemove(), "OutFrameRemove() failed");
VerifyOrQuit(ncpBuffer.InFrameGetPosition(pos2) == OT_ERROR_INVALID_STATE, "GetPosition failed");
}
printf(" -- PASS\n");
printf("\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -");
printf("\n Test 15: Test InFrameReset()");
printf("\nIterations: ");
for (j = 0; j < kTestIterationAttemps; j++)
{
uint16_t index;
bool addExtra = ((j % 7) != 0);
NcpFrameBuffer::Priority priority;
printf("*");
priority = ((j % 3) == 0) ? NcpFrameBuffer::kPriorityHigh : NcpFrameBuffer::kPriorityLow;
index = static_cast<uint16_t>(j % sizeof(sHexText));
SuccessOrQuit(ncpBuffer.InFrameBegin(priority), "InFrameBegin() failed");
SuccessOrQuit(ncpBuffer.InFrameFeedData(sHexText, index), "InFrameFeedData() failed.");
SuccessOrQuit(ncpBuffer.InFrameGetPosition(pos1), "InFrameGetPosition() failed");
SuccessOrQuit(ncpBuffer.InFrameFeedData(sMysteryText, sizeof(sHexText) - index), "InFrameFeedData() failed.");
VerifyOrQuit(ncpBuffer.InFrameGetDistance(pos1) == sizeof(sHexText) - index , "InFrameGetDistance() failed");
if (addExtra)
{
SuccessOrQuit(ncpBuffer.InFrameFeedData(sHelloText, sizeof(sHelloText)), "InFrameFeedData() failed.");
}
SuccessOrQuit(ncpBuffer.InFrameReset(pos1), "InFrameReset() failed.");
SuccessOrQuit(ncpBuffer.InFrameFeedData(sHexText + index, sizeof(sHexText) - index),
"InFrameOverwrite() failed.");
if (addExtra)
{
SuccessOrQuit(ncpBuffer.InFrameReset(pos1), "InFrameReset() failed.");
SuccessOrQuit(ncpBuffer.InFrameFeedData(sHexText + index, sizeof(sHexText) - index),
"InFrameOverwrite() failed.");
}
VerifyOrQuit(ncpBuffer.InFrameGetDistance(pos1) == sizeof(sHexText) - index,
"InFrameGetDistance() failed");
SuccessOrQuit(ncpBuffer.InFrameEnd(), "InFrameEnd() failed.");
SuccessOrQuit(ncpBuffer.OutFrameBegin(), "OutFrameBegin() failed");
ReadAndVerifyContent(ncpBuffer, sHexText, sizeof(sHexText));
SuccessOrQuit(ncpBuffer.OutFrameRemove(), "OutFrameRemove() failed");
}
printf(" -- PASS\n");
testFreeInstance(sInstance);
}