1140 lines
31 KiB
C
1140 lines
31 KiB
C
/* pipe.c - test microkernel target pipe APIs under VxMicro */
|
|
|
|
/*
|
|
* Copyright (c) 2012-2014 Wind River Systems, Inc.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are met:
|
|
*
|
|
* 1) Redistributions of source code must retain the above copyright notice,
|
|
* this list of conditions and the following disclaimer.
|
|
*
|
|
* 2) Redistributions in binary form must reproduce the above copyright notice,
|
|
* this list of conditions and the following disclaimer in the documentation
|
|
* and/or other materials provided with the distribution.
|
|
*
|
|
* 3) Neither the name of Wind River Systems nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software without
|
|
* specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/*
|
|
DESCRIPTION
|
|
This modules tests the following target pipe routines:
|
|
|
|
task_pipe_put(), task_pipe_put_wait(), task_pipe_put_wait_timeout()
|
|
task_pipe_get(), task_pipe_get_wait(), task_pipe_get_wait_timeout()
|
|
|
|
The following target pipe routine does not yet have a test case:
|
|
task_pipe_put_async()
|
|
*/
|
|
|
|
/* includes */
|
|
|
|
#include <nanokernel.h>
|
|
#include <nanokernel/cpu.h>
|
|
#include <tc_util.h>
|
|
#include <vxmicro.h>
|
|
|
|
/* defines */
|
|
|
|
#define NELEMENTS(x) (sizeof(x) / sizeof(x[0]))
|
|
|
|
#define ONE_SECOND (sys_clock_ticks_per_sec)
|
|
|
|
#define IRQ_PRIORITY 3
|
|
|
|
#define PIPE_SIZE 256 /* This must match the value in the VPF file */
|
|
|
|
/* typedefs */
|
|
|
|
typedef struct
|
|
{
|
|
int size; /* number of bytes to send/receive */
|
|
K_PIPE_OPTION options; /* options for task_pipe_XXX() APIs */
|
|
int sent; /* expected # of bytes sent */
|
|
int rcode; /* expected return code */
|
|
} SIZE_EXPECT;
|
|
|
|
/* locals */
|
|
|
|
|
|
static char txBuffer[PIPE_SIZE + 32];
|
|
static char rxBuffer[PIPE_SIZE + 32];
|
|
|
|
static SIZE_EXPECT all_N[] =
|
|
{
|
|
{0, _ALL_N, 0, RC_FAIL},
|
|
{1, _ALL_N, 1, RC_OK},
|
|
{PIPE_SIZE - 1, _ALL_N, PIPE_SIZE - 1, RC_OK},
|
|
{PIPE_SIZE, _ALL_N, PIPE_SIZE, RC_OK},
|
|
{PIPE_SIZE + 1, _ALL_N, 0, RC_FAIL}
|
|
};
|
|
|
|
static SIZE_EXPECT many_all_N[] =
|
|
{
|
|
{PIPE_SIZE / 3, _ALL_N, PIPE_SIZE / 3, RC_OK,},
|
|
{PIPE_SIZE / 3, _ALL_N, PIPE_SIZE / 3, RC_OK,},
|
|
{PIPE_SIZE / 3, _ALL_N, PIPE_SIZE / 3, RC_OK,},
|
|
{PIPE_SIZE / 3, _ALL_N, 0, RC_FAIL}
|
|
};
|
|
|
|
static SIZE_EXPECT one_to_N[] =
|
|
{
|
|
{0, _1_TO_N, 0, RC_FAIL},
|
|
{1, _1_TO_N, 1, RC_OK},
|
|
{PIPE_SIZE - 1, _1_TO_N, PIPE_SIZE - 1, RC_OK},
|
|
{PIPE_SIZE, _1_TO_N, PIPE_SIZE, RC_OK},
|
|
{PIPE_SIZE + 1, _1_TO_N, PIPE_SIZE, RC_OK}
|
|
};
|
|
|
|
static SIZE_EXPECT many_one_to_N[] =
|
|
{
|
|
{PIPE_SIZE / 3, _1_TO_N, PIPE_SIZE / 3, RC_OK},
|
|
{PIPE_SIZE / 3, _1_TO_N, PIPE_SIZE / 3, RC_OK},
|
|
{PIPE_SIZE / 3, _1_TO_N, PIPE_SIZE / 3, RC_OK},
|
|
{PIPE_SIZE / 3, _1_TO_N, 1, RC_OK},
|
|
{PIPE_SIZE / 3, _1_TO_N, 0, RC_FAIL}
|
|
};
|
|
|
|
static SIZE_EXPECT zero_to_N[] =
|
|
{
|
|
{0, _0_TO_N, 0, RC_FAIL},
|
|
{1, _0_TO_N, 1, RC_OK},
|
|
{PIPE_SIZE - 1, _0_TO_N, PIPE_SIZE - 1, RC_OK},
|
|
{PIPE_SIZE, _0_TO_N, PIPE_SIZE, RC_OK},
|
|
{PIPE_SIZE + 1, _0_TO_N, PIPE_SIZE, RC_OK}
|
|
};
|
|
|
|
static SIZE_EXPECT many_zero_to_N[] =
|
|
{
|
|
{PIPE_SIZE / 3, _0_TO_N, PIPE_SIZE / 3, RC_OK},
|
|
{PIPE_SIZE / 3, _0_TO_N, PIPE_SIZE / 3, RC_OK},
|
|
{PIPE_SIZE / 3, _0_TO_N, PIPE_SIZE / 3, RC_OK},
|
|
{PIPE_SIZE / 3, _0_TO_N, 1, RC_OK},
|
|
{PIPE_SIZE / 3, _0_TO_N, 0, RC_OK}
|
|
};
|
|
|
|
/*
|
|
* With the following 'wait' cases, the pipe buffer may be bypassed. It is
|
|
* thus possible to transmit and receive via the pipe more bytes than its
|
|
* buffer would allow.
|
|
*/
|
|
|
|
static SIZE_EXPECT wait_all_N[] =
|
|
{
|
|
{0, _ALL_N, 0, RC_FAIL},
|
|
{1, _ALL_N, 1, RC_OK},
|
|
{PIPE_SIZE - 1, _ALL_N, PIPE_SIZE - 1, RC_OK},
|
|
{PIPE_SIZE, _ALL_N, PIPE_SIZE, RC_OK},
|
|
{PIPE_SIZE + 1, _ALL_N, PIPE_SIZE + 1, RC_OK}
|
|
};
|
|
|
|
static SIZE_EXPECT wait_one_to_N[] =
|
|
{
|
|
{0, _1_TO_N, 0, RC_FAIL},
|
|
{1, _1_TO_N, 1, RC_OK},
|
|
{PIPE_SIZE - 1, _1_TO_N, PIPE_SIZE - 1, RC_OK},
|
|
{PIPE_SIZE, _1_TO_N, PIPE_SIZE, RC_OK},
|
|
{PIPE_SIZE + 1, _1_TO_N, PIPE_SIZE + 1, RC_OK}
|
|
};
|
|
|
|
static SIZE_EXPECT timeout_cases[] =
|
|
{
|
|
{0, _ALL_N, 0, RC_FAIL},
|
|
{1, _ALL_N, 0, RC_TIME},
|
|
{PIPE_SIZE - 1, _ALL_N, 0 , RC_TIME},
|
|
{PIPE_SIZE, _ALL_N, 0, RC_TIME},
|
|
{PIPE_SIZE + 1, _ALL_N, 0, RC_TIME},
|
|
{0, _1_TO_N, 0, RC_FAIL},
|
|
{1, _1_TO_N, 0, RC_TIME},
|
|
{PIPE_SIZE - 1, _1_TO_N, 0, RC_TIME},
|
|
{PIPE_SIZE, _1_TO_N, 0, RC_TIME},
|
|
{PIPE_SIZE + 1, _1_TO_N, 0, RC_TIME},
|
|
{0, _0_TO_N, 0, RC_FAIL},
|
|
{1, _0_TO_N, 0, RC_FAIL},
|
|
{PIPE_SIZE - 1, _0_TO_N, 0, RC_FAIL},
|
|
{PIPE_SIZE, _0_TO_N, 0, RC_FAIL},
|
|
{PIPE_SIZE + 1, _0_TO_N, 0, RC_FAIL}
|
|
};
|
|
|
|
/* globals */
|
|
|
|
extern ksem_t regSem;
|
|
extern ksem_t altSem;
|
|
extern ksem_t counterSem;
|
|
|
|
extern kpipe_t pipeId;
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* microObjectsInit - initialize objects used in this microkernel test suite
|
|
*
|
|
* RETURNS: N/A
|
|
*/
|
|
|
|
void microObjectsInit (void)
|
|
{
|
|
int i; /* loop counter */
|
|
|
|
for (i = 0; i < sizeof (rxBuffer); i++)
|
|
{
|
|
txBuffer[i] = (char) i;
|
|
}
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* receiveBufferCheck - check the contents of the receive buffer
|
|
*
|
|
* RETURNS: <size> on success, index of wrong character on failure
|
|
*/
|
|
|
|
int receiveBufferCheck
|
|
(
|
|
char * buffer, /* pointer to buffer to check */
|
|
int size /* number of bytes to check */
|
|
)
|
|
{
|
|
int j; /* loop counter */
|
|
|
|
for (j = 0; j < size; j++)
|
|
{
|
|
if (buffer[j] != (char) j)
|
|
{
|
|
return j;
|
|
}
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipePutHelperWork - helper routine to pipePutTest()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipePutHelperWork
|
|
(
|
|
SIZE_EXPECT * singleItems, /* testcase list (one item in the pipe) */
|
|
int nSingles, /* # of items in testcase */
|
|
SIZE_EXPECT * manyItems, /* testcase list (many items in the pipe) */
|
|
int nMany /* # of items in testcase */
|
|
)
|
|
{
|
|
int i; /* loop counter */
|
|
int j; /* loop counter */
|
|
int rv; /* value returned from task_pipe_get() */
|
|
int index; /* index to corrupted byte in buffer */
|
|
int bytesReceived; /* number of bytes received */
|
|
|
|
for (i = 0; i < nSingles; i++)
|
|
{
|
|
(void)task_sem_take_wait (altSem);
|
|
for (j = 0; j < sizeof (rxBuffer); j++)
|
|
{
|
|
rxBuffer[j] = 0;
|
|
}
|
|
|
|
rv = task_pipe_get (pipeId, rxBuffer, singleItems[i].size,
|
|
&bytesReceived, singleItems[i].options);
|
|
if (rv != singleItems[i].rcode)
|
|
{
|
|
TC_ERROR ("task_pipe_get(%d bytes) : Expected %d not %d.\n"
|
|
" bytesReceived = %d\n",
|
|
singleItems[i].size, singleItems[i].rcode,
|
|
rv, bytesReceived);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
if (bytesReceived != singleItems[i].sent)
|
|
{
|
|
TC_ERROR ("task_pipe_get(%d) : "
|
|
"Expected %d bytes to be received, not %d\n",
|
|
singleItems[i].size, singleItems[i].sent, bytesReceived);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
index = receiveBufferCheck (rxBuffer, bytesReceived);
|
|
if (index != bytesReceived)
|
|
{
|
|
TC_ERROR ("pipePutHelper: rxBuffer[%d] is %d, not %d\n",
|
|
index, rxBuffer[index], index);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
task_sem_give (counterSem);
|
|
task_sem_give (regSem);
|
|
}
|
|
|
|
/*
|
|
* Get items from the pipe. There should be more than one item
|
|
* stored in it.
|
|
*/
|
|
|
|
(void)task_sem_take_wait (altSem);
|
|
|
|
for (i = 0; i < nMany; i++)
|
|
{
|
|
for (j = 0; j < sizeof (rxBuffer); j++)
|
|
{
|
|
rxBuffer[j] = 0;
|
|
}
|
|
|
|
rv = task_pipe_get (pipeId, rxBuffer, manyItems[i].size,
|
|
&bytesReceived, manyItems[i].options);
|
|
|
|
if (rv != manyItems[i].rcode)
|
|
{
|
|
TC_ERROR ("task_pipe_get(%d bytes) : Expected %d not %d.\n"
|
|
" bytesReceived = %d, iteration: %d\n",
|
|
manyItems[i].size, manyItems[i].rcode,
|
|
rv, bytesReceived, i+1);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
if (bytesReceived != manyItems[i].sent)
|
|
{
|
|
TC_ERROR ("task_pipe_get(%d) : "
|
|
"Expected %d bytes to be received, not %d\n",
|
|
manyItems[i].size, manyItems[i].sent, bytesReceived);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
index = receiveBufferCheck (rxBuffer, bytesReceived);
|
|
if (index != bytesReceived)
|
|
{
|
|
TC_ERROR ("pipeGetHelper: rxBuffer[%d] is %d, not %d\n",
|
|
index, rxBuffer[index], index);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
task_sem_give (counterSem);
|
|
}
|
|
|
|
task_sem_give (regSem); /* Wake the RegressionTask */
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipePutHelper - helper routine to pipePutTest()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipePutHelper (void)
|
|
{
|
|
int rv; /* return value from pipePutHelperWork() */
|
|
|
|
rv = pipePutHelperWork (all_N, NELEMENTS(all_N),
|
|
many_all_N, NELEMENTS(many_all_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on all_N/many_all_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = pipePutHelperWork (one_to_N, NELEMENTS(one_to_N),
|
|
many_one_to_N, NELEMENTS(many_one_to_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on _1_TO_N/many_1_TO_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = pipePutHelperWork (zero_to_N, NELEMENTS(zero_to_N),
|
|
many_zero_to_N, NELEMENTS(many_zero_to_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on _0_TO_N/many_0_TO_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipePutTestWork - test task_pipe_put()
|
|
*
|
|
* This routine tests the task_pipe_put() API.
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipePutTestWork
|
|
(
|
|
SIZE_EXPECT * singleItems, /* testcase list (one item in the pipe) */
|
|
int nSingles, /* # of items in testcase */
|
|
SIZE_EXPECT * manyItems, /* testcase list (many items in the pipe) */
|
|
int nMany /* # of items in testcase */
|
|
)
|
|
{
|
|
int rv; /* return code from task_pipe_put() */
|
|
int i; /* loop counter */
|
|
int bytesWritten; /* # of bytes sent to pipe */
|
|
int nitem; /* expected item number processed by the other task */
|
|
|
|
task_sem_reset (counterSem);
|
|
|
|
for (i = 0; i < nSingles; i++)
|
|
{
|
|
rv = task_pipe_put (pipeId, txBuffer, singleItems[i].size,
|
|
&bytesWritten, singleItems[i].options);
|
|
if (rv != singleItems[i].rcode)
|
|
{
|
|
TC_ERROR ("task_pipe_put(%d) : Expected %d not %d.\n"
|
|
" bytesWritten = %d, Iteration: %d\n",
|
|
singleItems[i].size, singleItems[i].rcode,
|
|
rv, bytesWritten, i + 1);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
if (bytesWritten != singleItems[i].sent)
|
|
{
|
|
TC_ERROR ("task_pipe_put(%d) : "
|
|
"Expected %d bytes to be written, not %d\n",
|
|
singleItems[i].size, singleItems[i].sent, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
task_sem_give (altSem);
|
|
(void)task_sem_take_wait (regSem);
|
|
|
|
nitem = task_sem_count_get (counterSem) - 1;
|
|
if (nitem != i)
|
|
{
|
|
TC_ERROR ("Expected item number is %d, not %d\n",
|
|
i, nitem);
|
|
return TC_FAIL;
|
|
}
|
|
}
|
|
|
|
/* This time, more than one item will be in the pipe at a time */
|
|
|
|
task_sem_reset (counterSem);
|
|
|
|
for (i = 0; i < nMany; i++)
|
|
{
|
|
rv = task_pipe_put (pipeId, txBuffer, manyItems[i].size,
|
|
&bytesWritten, manyItems[i].options);
|
|
if (rv != manyItems[i].rcode)
|
|
{
|
|
TC_ERROR ("task_pipe_put(%d) : Expected %d not %d.\n"
|
|
" bytesWritten = %d, iteration: %d\n",
|
|
manyItems[i].size, manyItems[i].rcode,
|
|
rv, bytesWritten, i + 1);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
if (bytesWritten != manyItems[i].sent)
|
|
{
|
|
TC_ERROR ("task_pipe_put(%d) : "
|
|
"Expected %d bytes to be written, not %d\n",
|
|
manyItems[i].size, manyItems[i].sent, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
}
|
|
|
|
task_sem_give (altSem); /* Wake the alternate task */
|
|
/* wait for other task reading all the items from pipe */
|
|
(void)task_sem_take_wait (regSem);
|
|
|
|
if (task_sem_count_get (counterSem) != nMany)
|
|
{
|
|
TC_ERROR ("Expected number of items %d, not %d\n",
|
|
nMany, task_sem_count_get (counterSem));
|
|
return TC_FAIL;
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipePutTest - test task_pipe_put()
|
|
*
|
|
* This routine tests the task_pipe_put() API.
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipePutTest (void)
|
|
{
|
|
int rv; /* return value from pipePutTestWork() */
|
|
|
|
rv = pipePutTestWork (all_N, NELEMENTS(all_N),
|
|
many_all_N, NELEMENTS(many_all_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on _ALL_N/many_ALL_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = pipePutTestWork (one_to_N, NELEMENTS(one_to_N),
|
|
many_one_to_N, NELEMENTS(many_one_to_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on _1_TO_N/many_1_TO_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = pipePutTestWork (zero_to_N, NELEMENTS(zero_to_N),
|
|
many_zero_to_N, NELEMENTS(many_zero_to_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on _0_TO_N/many_0_TO_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipePutWaitHelper - help test task_pipe_put_wait()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipePutWaitHelper (void)
|
|
{
|
|
int i; /* loop counter */
|
|
int rv; /* return value from task_pipe_get_wait */
|
|
int bytesRead; /* # of bytes read from task_pipe_get_wait() */
|
|
|
|
(void)task_sem_take_wait (altSem); /* Wait until test is ready */
|
|
|
|
/* 1. task_pipe_get_wait() will force a context switch to RegressionTask() */
|
|
rv = task_pipe_get_wait (pipeId, rxBuffer, PIPE_SIZE,
|
|
&bytesRead, _ALL_N);
|
|
if ((rv != RC_OK) || (bytesRead != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n"
|
|
"Expected %d bytes to be read, not %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesRead);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* 2. task_pipe_get_wait() will force a context switch to RegressionTask(). */
|
|
rv = task_pipe_get_wait (pipeId, rxBuffer, PIPE_SIZE,
|
|
&bytesRead, _1_TO_N);
|
|
if ((rv != RC_OK) || (bytesRead != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n"
|
|
"Expected %d bytes to be read, not %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesRead);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/*
|
|
* Before emptying the pipe, check that task_pipe_get_wait() fails when
|
|
* using the _0_TO_N option.
|
|
*/
|
|
|
|
rv = task_pipe_get_wait (pipeId, rxBuffer, PIPE_SIZE / 2,
|
|
&bytesRead, _0_TO_N);
|
|
if (rv != RC_FAIL)
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n", RC_FAIL, rv);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* 3. Empty the pipe in two reads */
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
rv = task_pipe_get (pipeId, rxBuffer, PIPE_SIZE / 2,
|
|
&bytesRead, _0_TO_N);
|
|
if ((rv != RC_OK) || (bytesRead != PIPE_SIZE / 2))
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n"
|
|
"Expected %d bytes to be read, not %d\n",
|
|
RC_OK, rv, PIPE_SIZE / 2, bytesRead);
|
|
return TC_FAIL;
|
|
}
|
|
}
|
|
|
|
task_sem_give (regSem);
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipePutWaitTest - test task_pipe_put_wait()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipePutWaitTest (void)
|
|
{
|
|
int rv; /* return code from task_pipe_put_wait() */
|
|
int bytesWritten; /* # of bytes written to pipe */
|
|
|
|
/* 1. Fill the pipe */
|
|
rv = task_pipe_put_wait (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _ALL_N);
|
|
if ((rv != RC_OK) || (bytesWritten != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
task_sem_give (altSem); /* Wake the alternate task */
|
|
|
|
/* 2. task_pipe_put_wait() will force a context switch to AlternateTask(). */
|
|
rv = task_pipe_put_wait (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _ALL_N);
|
|
if ((rv != RC_OK) || (bytesWritten != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* 3. task_pipe_put_wait() will force a context switch to AlternateTask(). */
|
|
rv = task_pipe_put_wait (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _1_TO_N);
|
|
if ((rv != RC_OK) || (bytesWritten != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* This should return immediately as _0_TO_N with a wait is an error. */
|
|
rv = task_pipe_put_wait (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _0_TO_N);
|
|
if ((rv != RC_FAIL) || (bytesWritten != 0))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_FAIL, rv, 0, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* Wait for AlternateTask()'s pipePutWaitHelper() to finish */
|
|
(void)task_sem_take_wait (regSem);
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipePutTimeoutHelper - test task_pipe_get_wait_timeout()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipePutTimeoutHelper (void)
|
|
{
|
|
int i; /* loop counter */
|
|
int rv; /* return value from task_pipe_get_wait_timeout() */
|
|
int bytesRead; /* # of bytes read from task_pipe_get_wait_timeout() */
|
|
|
|
(void)task_sem_take_wait (altSem); /* Wait until test is ready */
|
|
|
|
/* 1. task_pipe_get_wait_timeout() will force a context switch to RegressionTask() */
|
|
rv = task_pipe_get_wait_timeout (pipeId, rxBuffer, PIPE_SIZE,
|
|
&bytesRead, _ALL_N, ONE_SECOND);
|
|
if ((rv != RC_OK) || (bytesRead != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n"
|
|
"Expected %d bytes to be read, not %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesRead);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* 2. task_pipe_get_wait_timeout() will force a context switch to RegressionTask(). */
|
|
rv = task_pipe_get_wait_timeout (pipeId, rxBuffer, PIPE_SIZE,
|
|
&bytesRead, _1_TO_N, ONE_SECOND);
|
|
if ((rv != RC_OK) || (bytesRead != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n"
|
|
"Expected %d bytes to be read, not %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesRead);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/*
|
|
* Before emptying the pipe, check that task_pipe_get_wait_timeout() fails when
|
|
* using the _0_TO_N option.
|
|
*/
|
|
|
|
rv = task_pipe_get_wait_timeout (pipeId, rxBuffer, PIPE_SIZE / 2,
|
|
&bytesRead, _0_TO_N, ONE_SECOND);
|
|
if (rv != RC_FAIL)
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n", RC_FAIL, rv);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* 3. Empty the pipe in two reads */
|
|
for (i = 0; i < 2; i++)
|
|
{
|
|
rv = task_pipe_get (pipeId, rxBuffer, PIPE_SIZE / 2,
|
|
&bytesRead, _0_TO_N);
|
|
if ((rv != RC_OK) || (bytesRead != PIPE_SIZE / 2))
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n"
|
|
"Expected %d bytes to be read, not %d\n",
|
|
RC_OK, rv, PIPE_SIZE / 2, bytesRead);
|
|
return TC_FAIL;
|
|
}
|
|
}
|
|
|
|
task_sem_give (regSem);
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipePutTimeoutTest - test task_pipe_put_wait_timeout()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipePutTimeoutTest (void)
|
|
{
|
|
int rv; /* return code from task_pipe_put_wait_timeout() */
|
|
int bytesWritten; /* # of bytes written to task_pipe_put_wait_timeout() */
|
|
|
|
/* 1. Fill the pipe */
|
|
rv = task_pipe_put_wait_timeout (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _ALL_N, ONE_SECOND);
|
|
if ((rv != RC_OK) || (bytesWritten != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* Timeout while waiting to put data into the pipe */
|
|
|
|
rv = task_pipe_put_wait_timeout (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _ALL_N, ONE_SECOND);
|
|
if ((rv != RC_TIME) || (bytesWritten != 0))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_TIME, rv, 0, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = task_pipe_put_wait_timeout (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _1_TO_N, ONE_SECOND);
|
|
if ((rv != RC_TIME) || (bytesWritten != 0))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_TIME, rv, 0, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
task_sem_give (altSem); /* Wake the alternate task */
|
|
|
|
/* 2. task_pipe_put_wait() will force a context switch to AlternateTask(). */
|
|
rv = task_pipe_put_wait_timeout (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _ALL_N, ONE_SECOND);
|
|
if ((rv != RC_OK) || (bytesWritten != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesWritten); return TC_FAIL; }
|
|
|
|
/* 3. task_pipe_put_wait() will force a context switch to AlternateTask(). */
|
|
rv = task_pipe_put_wait_timeout (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _1_TO_N, ONE_SECOND);
|
|
if ((rv != RC_OK) || (bytesWritten != PIPE_SIZE))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_OK, rv, PIPE_SIZE, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* This should return immediately as _0_TO_N with a wait is an error. */
|
|
rv = task_pipe_put_wait (pipeId, txBuffer, PIPE_SIZE,
|
|
&bytesWritten, _0_TO_N);
|
|
if ((rv != RC_FAIL) || (bytesWritten != 0))
|
|
{
|
|
TC_ERROR ("Return code: expected %d, got %d\n"
|
|
"Bytes written: expected %d, got %d\n",
|
|
RC_FAIL, rv, 0, bytesWritten);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/* Wait for AlternateTask()'s pipePutWaitHelper() to finish */
|
|
(void)task_sem_take_wait (regSem);
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipeGetTest - routine to test task_pipe_get()
|
|
*
|
|
* This routine tests the task_pipe_get() API. Some of this functionality
|
|
* has already been tested while testing task_pipe_put(). As a result, the
|
|
* only remaining functionality that needs to be checked are attempts to get
|
|
* data from an empty pipe.
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipeGetTest (void)
|
|
{
|
|
int i; /* loop counter */
|
|
int j; /* loop counter */
|
|
int rv; /* return code from task_pipe_get() */
|
|
int bytesRead; /* # of bytes read from task_pipe_get() */
|
|
int size[] ={1, PIPE_SIZE - 1, PIPE_SIZE, PIPE_SIZE + 1};
|
|
K_PIPE_OPTION options[] = {_ALL_N, _1_TO_N};
|
|
|
|
for (j = 0; j < NELEMENTS(options); j++)
|
|
{
|
|
for (i = 0; i < NELEMENTS(size); i++)
|
|
{
|
|
rv = task_pipe_get (pipeId, rxBuffer, size[i],
|
|
&bytesRead, options[j]);
|
|
if (rv != RC_FAIL)
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n", RC_FAIL, rv);
|
|
return TC_FAIL;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < NELEMENTS(size); i++)
|
|
{
|
|
rv = task_pipe_get (pipeId, rxBuffer, size[i],
|
|
&bytesRead, _0_TO_N);
|
|
if (rv != RC_OK)
|
|
{
|
|
TC_ERROR ("Expected return code %d, not %d\n", RC_OK, rv);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
if (bytesRead != 0)
|
|
{
|
|
TC_ERROR ("Expected <bytesRead> %d, not %d\n", 0, bytesRead);
|
|
return TC_FAIL;
|
|
}
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipeGetWaitHelperWork - test task_pipe_get_wait()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipeGetWaitHelperWork
|
|
(
|
|
SIZE_EXPECT * items, /* testcase list for task_pipe_get_wait() */
|
|
int nItems /* # of items in list */
|
|
)
|
|
{
|
|
int i; /* loop counter */
|
|
int rv; /* return value from task_pipe_put_wait() */
|
|
int bytesSent; /* # of bytes sent to task_pipe_put_wait() */
|
|
|
|
for (i = 0; i < nItems; i++)
|
|
{
|
|
/*
|
|
* Pipe should be empty. Most calls to task_pipe_get_wait() should
|
|
* block until the call to task_pipe_put() is performed in the routine
|
|
* pipeGetWaitHelperWork().
|
|
*/
|
|
|
|
bytesSent = 0;
|
|
rv = task_pipe_put_wait (pipeId, rxBuffer, items[i].size,
|
|
&bytesSent, items[i].options);
|
|
if ((rv != items[i].rcode) || (bytesSent != items[i].sent))
|
|
{
|
|
TC_ERROR ("Expected return value %d, got %d\n"
|
|
"Expected bytesSent = %d, got %d\n",
|
|
items[i].rcode, rv, 0, bytesSent);
|
|
return TC_FAIL;
|
|
}
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipeGetWaitHelper - test task_pipe_get_wait()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipeGetWaitHelper (void)
|
|
{
|
|
int rv; /* return coded form pipeGetWaitHelperWork() */
|
|
|
|
(void)task_sem_take_wait (altSem);
|
|
|
|
rv = pipeGetWaitHelperWork (wait_all_N, NELEMENTS(wait_all_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on _ALL_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = pipeGetWaitHelperWork (wait_one_to_N, NELEMENTS(wait_one_to_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on _1_TO_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipeGetWaitTestWork - test task_pipe_get_wait()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipeGetWaitTestWork
|
|
(
|
|
SIZE_EXPECT * items, /* testcase list for task_pipe_get_wait() */
|
|
int nItems /* # of items in list */
|
|
)
|
|
{
|
|
int i; /* loop counter */
|
|
int rv; /* return code from task_pipe_get_wait() */
|
|
int bytesRead; /* # of bytes read from task_pipe_get_wait() */
|
|
|
|
for (i = 0; i < nItems; i++)
|
|
{
|
|
/*
|
|
* Pipe should be empty. Most calls to task_pipe_get_wait() should
|
|
* block until the call to task_pipe_put() is performed in the routine
|
|
* pipeGetWaitHelperWork().
|
|
*/
|
|
|
|
rv = task_pipe_get_wait (pipeId, rxBuffer, items[i].size,
|
|
&bytesRead, items[i].options);
|
|
if ((rv != items[i].rcode) || (bytesRead != items[i].sent))
|
|
{
|
|
TC_ERROR ("Expected return value %d, got %d\n"
|
|
"Expected bytesRead = %d, got %d\n",
|
|
items[i].rcode, rv, 0, bytesRead);
|
|
return TC_FAIL;
|
|
}
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipeGetWaitTest - test task_pipe_get_wait()
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipeGetWaitTest (void)
|
|
{
|
|
int rv; /* return code from pipeGetWaitTestWork() */
|
|
int bytesRead; /* # of bytes read from task_pipe_get_waitait() */
|
|
|
|
task_sem_give (altSem); /* Wake AlternateTask */
|
|
|
|
rv = pipeGetWaitTestWork (wait_all_N, NELEMENTS(wait_all_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on _ALL_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = pipeGetWaitTestWork (wait_one_to_N, NELEMENTS(wait_one_to_N));
|
|
if (rv != TC_PASS)
|
|
{
|
|
TC_ERROR ("Failed on _1_TO_N test\n");
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = task_pipe_get_wait (pipeId, rxBuffer, PIPE_SIZE,
|
|
&bytesRead, _0_TO_N);
|
|
if (rv != RC_FAIL)
|
|
{
|
|
TC_ERROR ("Expected return code of %d, not %d\n", RC_FAIL, rv);
|
|
return TC_FAIL;
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* pipeGetTimeoutTest - test remaining task_pipe_get_wait_timeout() functionality
|
|
*
|
|
* RETURNS: TC_PASS on success, TC_FAIL on failure
|
|
*/
|
|
|
|
int pipeGetTimeoutTest (void)
|
|
{
|
|
int i; /* loop counter */
|
|
int rv; /* return value from task_pipe_get_wait_timeout() */
|
|
int bytesRead; /* # of bytes read from task_pipe_get_wait_timeout() */
|
|
|
|
for (i = 0; i < NELEMENTS(timeout_cases); i++)
|
|
{
|
|
rv = task_pipe_get_wait_timeout (pipeId, rxBuffer, timeout_cases[i].size,
|
|
&bytesRead, timeout_cases[i].options, ONE_SECOND);
|
|
if ((rv != timeout_cases[i].rcode) ||
|
|
(bytesRead != timeout_cases[i].sent))
|
|
{
|
|
TC_ERROR ("Expected return code %d, got %d\n"
|
|
"Expected <bytesRead> %d, got %d\n"
|
|
"Iteration %d\n",
|
|
timeout_cases[i].rcode, rv, timeout_cases[i].sent,
|
|
bytesRead, i + 1);
|
|
return TC_FAIL;
|
|
}
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* AlternateTask - alternate task in the test suite
|
|
*
|
|
* This routine runs at a lower priority than RegressionTask().
|
|
*
|
|
* RETURNS: TC_PASS or TC_FAIL
|
|
*/
|
|
|
|
int AlternateTask (void)
|
|
{
|
|
int rv; /* return code from each set of test cases */
|
|
|
|
rv = pipePutHelper ();
|
|
if (rv != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = pipePutWaitHelper ();
|
|
if (rv != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
rv = pipePutTimeoutHelper ();
|
|
if (rv != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/*
|
|
* There is no pipeGetHelper() as the task_pipe_get() checks have
|
|
* either been done in pipePutHelper(), or pipeGetTest().
|
|
*/
|
|
|
|
rv = pipeGetWaitHelper ();
|
|
if (rv != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
/*
|
|
* There is no pipeGetTimeoutHelper() as the task_pipe_get_wait_timeout() checks
|
|
* have either been done in pipePutTimeoutHelper() or
|
|
* pipeGetTimeoutTest().
|
|
*/
|
|
|
|
return TC_PASS;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
*
|
|
* RegressionTask - main task in the test suite
|
|
*
|
|
* This is the entry point to the VxMicro target pipe test suite.
|
|
*
|
|
* RETURNS: TC_PASS or TC_FAIL
|
|
*/
|
|
|
|
int RegressionTask (void)
|
|
{
|
|
int tcRC; /* test case return code */
|
|
|
|
microObjectsInit ();
|
|
|
|
TC_PRINT ("Testing task_pipe_put() ...\n");
|
|
tcRC = pipePutTest ();
|
|
if (tcRC != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
TC_PRINT ("Testing task_pipe_put_wait() ...\n");
|
|
tcRC = pipePutWaitTest ();
|
|
if (tcRC != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
TC_PRINT ("Testing task_pipe_put_wait_timeout() ...\n");
|
|
tcRC = pipePutTimeoutTest ();
|
|
if (tcRC != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
TC_PRINT ("Testing task_pipe_get() ...\n");
|
|
tcRC = pipeGetTest ();
|
|
if (tcRC != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
TC_PRINT ("Testing task_pipe_get_wait() ...\n");
|
|
tcRC = pipeGetWaitTest ();
|
|
if (tcRC != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
TC_PRINT ("Testing task_pipe_get_wait_timeout() ...\n");
|
|
tcRC = pipeGetTimeoutTest ();
|
|
if (tcRC != TC_PASS)
|
|
{
|
|
return TC_FAIL;
|
|
}
|
|
|
|
return TC_PASS;
|
|
}
|