Files
yttrium-virtio-gpu/vioserial/app/main.cpp
T
Yuri Benditovich 064c9b2946 vioser-test: add flexibility to the test
If the port can't be open (probably opened by vdservice), go to
the next one.
Add ability to increase write buffer size and send
entire buffer filled by characters without getting data from the
console.
This helps testing corner cases of vioser.sys, for example:
configure additional test port port with tcp socket backend,
connect to it with 'nc', press ^Z to suspend the 'nc' and send
several large (512K) buffers.
At some point the write does not return immediately and closing
test application causes cancellation flow.
Another scenarion: if 1M buffer sent, the driver fails the operation
due to too large SG table.

Signed-off-by: Yuri Benditovich <[email protected]>
2019-12-11 13:55:04 +01:00

291 lines
5.5 KiB
C++

//#include <basetyps.h>
#include "device.h"
#include "assert.h"
#pragma warning(default:4201)
static ULONG write_buffer_size = 4096;
static BOOL write_send_auto = FALSE;
BOOL
GetInfoTest(
__in CDevice *pDev
)
{
PVOID buf = NULL;
PVIRTIO_PORT_INFO inf = NULL;
size_t len;
if (!pDev) return FALSE;
len = sizeof(VIRTIO_PORT_INFO);
buf = GlobalAlloc(0, len);
if (!buf) return FALSE;
if (!pDev->GetInfo(buf, &len))
{
GlobalFree(buf);
buf = GlobalAlloc(0, len);
if (!buf) return FALSE;
if (!pDev->GetInfo(buf, &len))
{
GlobalFree(buf);
return FALSE;
}
}
inf = (PVIRTIO_PORT_INFO)buf;
printf("Id = %d\n", inf->Id);
printf("OutVqFull = %d\n", inf->OutVqFull);
printf("HostConnected = %d\n", inf->HostConnected);
printf("GuestConnected = %d\n", inf->GuestConnected);
if (len > sizeof(VIRTIO_PORT_INFO) && inf->Name[0])
{
printf("Id = %s\n", inf->Name);
}
GlobalFree(buf);
return TRUE;
}
BOOL
WriteTest(
__in CDevice *pDev,
__in BOOLEAN ovrl
)
{
PUCHAR buf = NULL;
BOOLEAN res = TRUE;
int i;
size_t size = write_buffer_size;
if (!pDev) return FALSE;
printf("%s.\n", __FUNCTION__);
buf = (PUCHAR)GlobalAlloc(0, size);
if( buf == NULL )
{
printf("%s: Could not allocate %zd "
"bytes buf\n", __FUNCTION__, size);
return FALSE;
}
for(i = 0 ;i < (int)size; i++)
{
if (!write_send_auto)
{
int ch = getchar();
buf[i] = (char)ch;
if (ch == '\n') break;
}
else
{
buf[i] = 'a' + i % 20;
if (i == (size - 1))
{
buf[i] = '\n';
}
}
}
size = i;
res = ovrl ? pDev->WriteEx(buf, &size) : pDev->Write(buf, &size);
if (!res)
{
printf ("%s: WriteFile failed: "
"Error %d\n", __FUNCTION__, GetLastError());
}
else
{
printf ("%s: WriteFile OK: "
"snd %zd bytes\n\n", __FUNCTION__, size);
if (!write_send_auto) {
printf("%s\n", buf);
}
}
GlobalFree(buf);
return res;
}
BOOL
WriteTestCycl(
__in CDevice *pDev,
__in BOOLEAN ovrl
)
{
int ch;
for (;;)
{
if(!WriteTest(pDev, ovrl)) return FALSE;
ch = getchar();
if(ch == EOF) break;
putchar(ch);
}
return TRUE;
}
BOOL
ReadTest(
__in CDevice *pDev,
__in BOOLEAN ovrl
)
{
PUCHAR buf = NULL;
BOOLEAN res = TRUE;
size_t size = 4096;
if (!pDev) return FALSE;
printf("%s.\n", __FUNCTION__);
buf = (PUCHAR)GlobalAlloc(0, size);
if( buf == NULL )
{
printf("%s: Could not allocate %zd "
"bytes buf\n", __FUNCTION__, size);
return FALSE;
}
res = ovrl ? pDev->ReadEx(buf, &size) : pDev->Read(buf, &size);
if (!res)
{
printf ("%s: ReadFile failed: "
"Error %d\n", __FUNCTION__, GetLastError());
}
else
{
printf ("%s: ReadFile OK: "
"rcv %zd bytes\n\n", __FUNCTION__, size);
printf ("%s\n", buf);
}
GlobalFree(buf);
return res;
}
BOOL
ReadTestCycl(
__in CDevice *pDev,
__in BOOLEAN ovrl
)
{
int ch;
for (;;)
{
if(!ReadTest(pDev, ovrl)) return FALSE;
if(_kbhit())
{
ch = getchar();
if(ch == EOF) break;
putchar(ch);
}
}
return TRUE;
}
ULONG
_cdecl
wmain(
__in ULONG argc,
__in_ecount(argc) PWCHAR argv[]
)
{
int ch;
CDevice *m_pDev;
BOOLEAN stoptest = FALSE;
BOOLEAN ovrl = TRUE;
UINT ifIndex = 0;
if(argc == 2)
{
if (_wcsicmp(L"-n", argv[1]) == 0) {
ovrl = FALSE;
}
}
if (ovrl)
{
printf("Running in non-blocking mode.\n");
}
else
{
printf("Running in blocking mode.\n");
}
m_pDev = new CDevice;
if (!m_pDev)
{
return 1;
}
while (!m_pDev->Init(ovrl, ifIndex))
{
ifIndex++;
if (ifIndex >= 4)
{
delete m_pDev;
return 2;
}
}
while (!stoptest)
{
ch = getchar();
while(getchar()!='\n');
switch (ch)
{
case 'i':
case 'I':
GetInfoTest(m_pDev);
break;
case '+':
write_buffer_size = write_buffer_size * 2;
printf("write_buffer_size = %d\n", write_buffer_size);
break;
case '-':
if (write_buffer_size > 16) {
write_buffer_size = write_buffer_size / 2;
}
printf("write_buffer_size = %d\n", write_buffer_size);
break;
case '!':
write_send_auto = !write_send_auto;
printf("write_send_auto = %d\n", write_send_auto);
break;
case 'r':
case 'R':
ReadTest(m_pDev, ovrl);
break;
case 'f':
case 'F':
ReadTestCycl(m_pDev, ovrl);
break;
case 'w':
case 'W':
WriteTest(m_pDev, ovrl);
break;
case 's':
case 'S':
WriteTestCycl(m_pDev, ovrl);
break;
case 'q':
case 'Q':
stoptest = TRUE;
break;
}
}
delete m_pDev;
return 0;
}