/***************************************************************************
*   emstest2.c                                                             *
*   MODULE:  EMSIF                                                         *
*   OS:      DOS                                                           *
*   VERSION: 1.2                                                           *
*   DATE:    12/01/91                                                      *
*                                                                          *
*   Copyright (c) 1991 James W. Birdsall. All Rights Reserved.             *
*                                                                          *
*   Requires emsif.h, testutil.h, and emstest.h to compile.                *
*   Compiles under Borland C++ 2.0, TC 2.0, or MSC 6.0A.                   *
*                                                                          *
*   Regression test and example for EMSIF. See EMSTEST.C for more detail.  *
*                                                                          *
***************************************************************************/

/*
** system includes <>
*/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/*
** custom includes ""
*/

#include "testutil.h"

#include "emsif.h"
#include "emstest.h"


/*
** local #defines
*/

#define UCF                      unsigned char far

/*
** Checks to see if a region of memory is still incrementing word values,
** handles cleanup and exit if not.
*/
#define WORDCHECK(buf, len, msg)                                \
    if (farincwordcheck((UCF *) (buf), (len), 0) != 0) {        \
        printf("Copy corrupted %s.\n", (msg)); EMMfree(handle); \
        free(testbuf); exit(3); }

/*
** Check source and destination buffers, respectively.
*/
#define SRCWORDCHECK(buf, len)    WORDCHECK(buf, len, "source buffer")
#define CPYWORDCHECK(buf, len)    WORDCHECK(buf, len, "copied bytes")

/*
** Checks to see if a region of memory is still filled with a given value,
** handles cleanup and exit if not.
*/
#define MEMCHECK(buf, len, val)                          \
    if (farmemcheck((UCF *) (buf), (len), (val)) != 0) { \
        printf("Copy corrupted destination.\n");         \
        EMMfree(handle); free(testbuf); exit(3); }

/*
** Checks buffer for nonzero values.
*/
#define ZEROCHECK(buf, len)       MEMCHECK(buf, len, '\0')

/*
** Compares two regions of memory, handles cleanup and exit if not the same.
*/
#define MEMCMP(buf1, buf2, len)                                          \
    if (FMEMCMP((void far *) (buf1), (void far *) (buf2), (len)) != 0) { \
        printf("Copy corrupted copied bytes.\n"); EMMfree(handle);       \
        free(testbuf); exit(3); }


/*
** misc: copyright strings, version macros, etc.
*/

/*
** typedefs
*/

/*
** global variables
*/

/* see EMSTEST.C for info */
extern int testno;
extern unsigned char far *frameptr[];
extern char *gblmsg;


/*
** static globals
*/

/*
** function prototypes
*/

static void do_nshortcopy_tests(void);
static void do_ishortcopy_tests(void);


/*
** functions
*/


/***************************************************************************
*   FUNCTION: DO_SHORTCOPY_TESTS                                           *
*                                                                          *
*   DESCRIPTION:                                                           *
*                                                                          *
*       Central dispatching function for short copy tests.                 *
*                                                                          *
*   ENTRY:                                                                 *
*                                                                          *
*       Void.                                                              *
*                                                                          *
*   EXIT:                                                                  *
*                                                                          *
*       Void.                                                              *
*                                                                          *
*   CONSTRAINTS/SIDE EFFECTS:                                              *
*                                                                          *
***************************************************************************/
void do_shortcopy_tests(void)
{
    do_nshortcopy_tests();
    do_ishortcopy_tests();
    return;
} /* end of do_shortcopy_tests() */


/***************************************************************************
*   FUNCTION: DO_NSHORTCOPY_TESTS  (STATIC)                                *
*                                                                          *
*   DESCRIPTION:                                                           *
*                                                                          *
*       Tests EMSIF functions EMMcopyto() and EMMcopyfrom() with copies    *
*       shorter than one EMS page ( <= 16384 bytes ).                      *
*                                                                          *
*   ENTRY:                                                                 *
*                                                                          *
*       Void.                                                              *
*                                                                          *
*   EXIT:                                                                  *
*                                                                          *
*       Void.                                                              *
*                                                                          *
*   CONSTRAINTS/SIDE EFFECTS:                                              *
*                                                                          *
***************************************************************************/
static void do_nshortcopy_tests(void)
{
    unsigned char *testbuf;
    int handle;
    int status;
    unsigned long ticks, totticks;
    int loop;

    /* allocate memory to test against */
    testbuf = (unsigned char *) malloc(16384);
    if (testbuf == (unsigned char *) NULL)
    {
        printf("Cannot allocate test memory. Aborting.\n");
        exit(1);
    }

    /* now allocate a page of EMS to test with */
    handle = test_EMMallocpages(1);

    /* fill test buffer with incrementing word pattern */
    farincwordfill((UCF *) testbuf, 16384, 0);

    /* fill EMS page with a different pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* try a bad copy first */
    TESTHEADER();
    printf("Calling EMMcopyto() with bad offset.\n");
    printf("Should fail.\n");
    status = EMMcopyto(5L, (UCF *) testbuf, handle, 20000L);
    nofailcheck("EMMcopyto()", status, testbuf, handle, 0);
    weirdretchk("EMMcopyto()", status, testbuf, handle, 0);
    weirdcodechk("EMMcopyto()", EMM_BADOFFSET, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    ZEROCHECK(frameptr[0], 16384);
    printf("EMMcopyto() failed OK.\n");
    TESTTAILER();

    /* and another */
    TESTHEADER();
    printf("Calling EMMcopyto() with block that runs off end of EMS.\n");
    printf("Should fail.\n");
    status = EMMcopyto(500L, (UCF *) testbuf, handle, 16000L);
    nofailcheck("EMMcopyto()", status, testbuf, handle, 0);
    weirdretchk("EMMcopyto()", status, testbuf, handle, 0);
    weirdcodechk("EMMcopyto()", EMM_BADOFFSET, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    ZEROCHECK(frameptr[0], 16384);
    printf("EMMcopyto() failed OK.\n");
    TESTTAILER();

    /* test zero-length copy */
    TESTHEADER();
    printf("Calling EMMcopyto() with zero-length source block.\n");
    printf("Should succeed.\n");
    status = EMMcopyto(0L, (UCF *) testbuf, handle, 0L);
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    ZEROCHECK(frameptr[0], 16384);
    printf("EMMcopyto() succeeded.\n");
    TESTTAILER();

    /* test copy of even number of bytes to 0 offset */
    TESTHEADER();
    printf("Calling EMMcopyto() to copy 50 bytes to offset 0.\n");
    status = EMMcopyto(50L, (UCF *) testbuf, handle, 0L);
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    CPYWORDCHECK(frameptr[0], 50);
    ZEROCHECK((frameptr[0] + 50), 16384 - 50);
    printf("EMMcopyto() succeeded.\n");
    TESTTAILER();

    /* restore EMS pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy of even number of bytes to even offset */
    TESTHEADER();
    printf("Calling EMMcopyto() to copy 50 bytes to even offset.\n");
    status = EMMcopyto(50L, (UCF *) testbuf, handle, 498L);
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    CPYWORDCHECK((frameptr[0] + 498), 50);
    ZEROCHECK(frameptr[0], 498);
    ZEROCHECK((frameptr[0] + 498 + 50), ((16384 - 498) - 50));
    printf("EMMcopyto() succeeded.\n");
    TESTTAILER();

    /* restore EMS pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy of even number of bytes to odd offset */
    TESTHEADER();
    printf("Calling EMMcopyto() to copy 50 bytes to odd offset.\n");
    status = EMMcopyto(50L, (UCF *) testbuf, handle, 777L);
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    CPYWORDCHECK((frameptr[0] + 777), 50);
    ZEROCHECK(frameptr[0], 777);
    ZEROCHECK((frameptr[0] + 777 + 50), ((16384 - 777) - 50));
    printf("EMMcopyto() succeeded.\n");
    TESTTAILER();

    /* restore EMS pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy of even number of bytes to offset just before end */
    TESTHEADER();
    printf(
         "Calling EMMcopyto() to copy 50 bytes to just before end of page.\n");
    status = EMMcopyto(50L, (UCF *) testbuf, handle, (16384L - 50L));
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    CPYWORDCHECK((frameptr[0] + (16384 - 50)), 50);
    ZEROCHECK(frameptr[0], (16384 - 50));
    printf("EMMcopyto() succeeded.\n");
    TESTTAILER();

    /* restore EMS pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy of odd number of bytes to 0 offset */
    TESTHEADER();
    printf("Calling EMMcopyto() to copy 77 bytes to offset 0.\n");
    status = EMMcopyto(77L, (UCF *) testbuf, handle, 0L);
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    MEMCMP(frameptr[0], testbuf, 77);
    ZEROCHECK((frameptr[0] + 77), 16384 - 77);
    printf("EMMcopyto() succeeded.\n");
    TESTTAILER();

    /* restore EMS pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy of odd number of bytes to even offset */
    TESTHEADER();
    printf("Calling EMMcopyto() to copy 77 bytes to even offset.\n");
    status = EMMcopyto(77L, (UCF *) testbuf, handle, 498L);
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    MEMCMP((frameptr[0] + 498), testbuf, 77);
    ZEROCHECK(frameptr[0], 498);
    ZEROCHECK((frameptr[0] + 498 + 77), ((16384 - 498) - 77));
    printf("EMMcopyto() succeeded.\n");
    TESTTAILER();

    /* restore EMS pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy of odd number of bytes to odd offset */
    TESTHEADER();
    printf("Calling EMMcopyto() to copy 77 bytes to odd offset.\n");
    status = EMMcopyto(77L, (UCF *) testbuf, handle, 777L);
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    MEMCMP((frameptr[0] + 777), testbuf, 77);
    ZEROCHECK(frameptr[0], 777);
    ZEROCHECK((frameptr[0] + 777 + 77), ((16384 - 777) - 77));
    printf("EMMcopyto() succeeded.\n");
    TESTTAILER();

    /* restore EMS pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy of odd number of bytes to offset just before end */
    TESTHEADER();
    printf(
         "Calling EMMcopyto() to copy 77 bytes to just before end of page.\n");
    status = EMMcopyto(77L, (UCF *) testbuf, handle, (16384L - 77L));
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    MEMCMP((frameptr[0] + (16384 - 77)), testbuf, 77);
    ZEROCHECK(frameptr[0], (16384 - 77));
    printf("EMMcopyto() succeeded.\n");
    TESTTAILER();

    /* restore EMS pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* copy entire page by words */
    TESTHEADER();
    printf("Calling EMMcopyto() to fill EMS page in chunks of 2 bytes.\n");
    totticks = 0L;
    for (loop = 0; loop < 16384; loop += 2)
    {
        ticks = get_tick();
        status = EMMcopyto(2L, (UCF *) (testbuf + loop), handle,
                                                         (unsigned long) loop);
        totticks += (get_tick() - ticks);
        TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    }
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    MEMCMP(frameptr[0], testbuf, 16384);
    printf("EMMcopyto() succeeded, took about %lu ticks.\n", totticks);
    TESTTAILER();

    /* restore EMS pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* copy entire page at once */
    TESTHEADER();
    printf("Calling EMMcopyto() to copy entire page at once.\n");
    ticks = get_tick();
    status = EMMcopyto(16384L, (UCF *) testbuf, handle, 0L);
    ticks = get_tick() - ticks;
    TRIPLECHECK("EMMcopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    MEMCMP(frameptr[0], testbuf, 16384);
    printf("EMMcopyto() succeeded, took about %lu ticks.\n", ticks);
    TESTTAILER();


    /* fill EMS page with incrementing word pattern */
    test_EMMmappage(0, handle, 0);
    farincwordfill(frameptr[0], 16384, 0);

    /* fill test buffer with a different pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* try a bad copy first */
    TESTHEADER();
    printf("Calling EMMcopyfrom() with bad offset.\n");
    printf("Should fail.\n");
    status = EMMcopyfrom(5L, handle, 20000L, (UCF *) testbuf);
    nofailcheck("EMMcopyfrom()", status, testbuf, handle, 0);
    weirdretchk("EMMcopyfrom()", status, testbuf, handle, 0);
    weirdcodechk("EMMcopyfrom()", EMM_BADOFFSET, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    ZEROCHECK(testbuf, 16384);
    printf("EMMcopyfrom() failed OK.\n");
    TESTTAILER();

    /* and another */
    TESTHEADER();
    printf("Calling EMMcopyfrom() with block that runs off end of EMS.\n");
    printf("Should fail.\n");
    status = EMMcopyfrom(500L, handle, 16000L, (UCF *) testbuf);
    nofailcheck("EMMcopyfrom()", status, testbuf, handle, 0);
    weirdretchk("EMMcopyfrom()", status, testbuf, handle, 0);
    weirdcodechk("EMMcopyfrom()", EMM_BADOFFSET, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    ZEROCHECK(testbuf, 16384);
    printf("EMMcopyfrom() failed OK.\n");
    TESTTAILER();

    /* test zero-length copy */
    TESTHEADER();
    printf("Calling EMMcopyfrom() with zero-length source block.\n");
    printf("Should succeed.\n");
    status = EMMcopyfrom(0L, handle, 0L, (UCF *) testbuf);
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    ZEROCHECK(testbuf, 16384);
    printf("EMMcopyfrom() succeeded.\n");
    TESTTAILER();

    /* test copy of even number of bytes to 0 offset */
    TESTHEADER();
    printf("Calling EMMcopyfrom() to copy 50 bytes to offset 0.\n");
    status = EMMcopyfrom(50L, handle, 0L, (UCF *) testbuf);
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    CPYWORDCHECK(testbuf, 50);
    ZEROCHECK((testbuf + 50), 16384 - 50);
    printf("EMMcopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy of even number of bytes to even offset */
    TESTHEADER();
    printf("Calling EMMcopyfrom() to copy 50 bytes to even offset.\n");
    status = EMMcopyfrom(50L, handle, 0L, (UCF *) (testbuf + 498));
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    CPYWORDCHECK((testbuf + 498), 50);
    ZEROCHECK(testbuf, 498);
    ZEROCHECK((testbuf + 498 + 50), ((16384 - 498) - 50));
    printf("EMMcopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy of even number of bytes to odd offset */
    TESTHEADER();
    printf("Calling EMMcopyfrom() to copy 50 bytes to odd offset.\n");
    status = EMMcopyfrom(50L, handle, 0L, (UCF *) (testbuf + 777));
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    CPYWORDCHECK((testbuf + 777), 50);
    ZEROCHECK(testbuf, 777);
    ZEROCHECK((testbuf + 777 + 50), ((16384 - 777) - 50));
    printf("EMMcopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy of even number of bytes to offset just before end */
    TESTHEADER();
    printf(
         "Calling EMMcopyfrom() to copy 50 bytes to just before end of page.\n");
    status = EMMcopyfrom(50L, handle, 0L, (UCF *) (testbuf + (16384 - 50)));
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    CPYWORDCHECK((testbuf + (16384 - 50)), 50);
    ZEROCHECK(testbuf, (16384 - 50));
    printf("EMMcopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy of odd number of bytes to 0 offset */
    TESTHEADER();
    printf("Calling EMMcopyfrom() to copy 77 bytes to offset 0.\n");
    status = EMMcopyfrom(77L, handle, 0L, (UCF *) testbuf);
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    MEMCMP(testbuf, frameptr[0], 77);
    ZEROCHECK((testbuf + 77), 16384 - 77);
    printf("EMMcopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy of odd number of bytes to even offset */
    TESTHEADER();
    printf("Calling EMMcopyfrom() to copy 77 bytes to even offset.\n");
    status = EMMcopyfrom(77L, handle, 0L, (UCF *) (testbuf + 498));
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    MEMCMP((testbuf + 498), frameptr[0], 77);
    ZEROCHECK(testbuf, 498);
    ZEROCHECK((testbuf + 498 + 77), ((16384 - 498) - 77));
    printf("EMMcopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy of odd number of bytes to odd offset */
    TESTHEADER();
    printf("Calling EMMcopyfrom() to copy 77 bytes to odd offset.\n");
    status = EMMcopyfrom(77L, handle, 0L, (UCF *) (testbuf + 777));
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    MEMCMP((testbuf + 777), frameptr[0], 77);
    ZEROCHECK(testbuf, 777);
    ZEROCHECK((testbuf + 777 + 77), ((16384 - 777) - 77));
    printf("EMMcopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy of odd number of bytes to offset just before end */
    TESTHEADER();
    printf(
       "Calling EMMcopyfrom() to copy 77 bytes to just before end of page.\n");
    status = EMMcopyfrom(77L, handle, 0L, (UCF *) (testbuf + (16384 - 77)));
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    MEMCMP((testbuf + (16384 - 77)), frameptr[0], 77);
    ZEROCHECK(testbuf, (16384 - 77));
    printf("EMMcopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* copy entire page by words */
    TESTHEADER();
    printf("Calling EMMcopyfrom() to fill buffer in chunks of 2 bytes.\n");
    totticks = 0L;
    for (loop = 0; loop < 16384; loop += 2)
    {
        ticks = get_tick();
        status = EMMcopyfrom(2L, handle, (unsigned long) loop,
                                                     (UCF *) (testbuf + loop));
        totticks += (get_tick() - ticks);
        TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    }
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    MEMCMP(testbuf, frameptr[0], 16384);
    printf("EMMcopyfrom() succeeded, took about %lu ticks.\n", totticks);
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* copy entire page at once */
    TESTHEADER();
    printf("Calling EMMcopyfrom() to copy entire page at once.\n");
    ticks = get_tick();
    status = EMMcopyfrom(16384L, handle, 0L, (UCF *) testbuf);
    ticks = get_tick() - ticks;
    TRIPLECHECK("EMMcopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    MEMCMP(testbuf, frameptr[0], 16384);
    printf("EMMcopyfrom() succeeded, took about %lu ticks.\n", ticks);
    TESTTAILER();

    /* clean up */
    test_EMMfree(handle);
    free(testbuf);

    return;
} /* end of do_nshortcopy_tests() */


/***************************************************************************
*   FUNCTION: DO_ISHORTCOPY_TESTS  (STATIC)                                *
*                                                                          *
*   DESCRIPTION:                                                           *
*                                                                          *
*       Tests EMSIF functions _EMMicopyto() and _EMMicopyfrom() with       *
*       copies shorter than one EMS page ( <= 16384 bytes ).               *
*                                                                          *
*   ENTRY:                                                                 *
*                                                                          *
*       Void.                                                              *
*                                                                          *
*   EXIT:                                                                  *
*                                                                          *
*       Void.                                                              *
*                                                                          *
*   CONSTRAINTS/SIDE EFFECTS:                                              *
*                                                                          *
***************************************************************************/
static void do_ishortcopy_tests(void)
{
    unsigned char *testbuf;
    int handle;
    int status;
    unsigned long ticks, totticks;
    int loop;

    /* allocate memory to test against */
    testbuf = (unsigned char *) malloc(16384);
    if (testbuf == (unsigned char *) NULL)
    {
        printf("Cannot allocate test memory. Aborting.\n");
        exit(1);
    }

    /* now allocate a page of EMS to test with */
    handle = test_EMMallocpages(1);

    /* fill test buffer with incrementing word pattern */
    farincwordfill((UCF *) testbuf, 16384, 0);

    /* fill EMS page with a different pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* try a bad copy first */
    TESTHEADER();
    printf("Calling _EMMicopyto() with bad offset.\n");
    printf("Should fail.\n");
    status = EMMicopyto(5L, 2, 2, (UCF *) testbuf, handle, 20000L);
    nofailcheck("_EMMicopyto()", status, testbuf, handle, 0);
    weirdretchk("_EMMicopyto()", status, testbuf, handle, 0);
    weirdcodechk("_EMMicopyto()", EMM_BADOFFSET, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    ZEROCHECK(frameptr[0], 16384);
    printf("_EMMicopyto() failed OK.\n");
    TESTTAILER();

    /* and another */
    TESTHEADER();
    printf("Calling _EMMicopyto() with block that runs off end of EMS.\n");
    printf("Should fail.\n");
    status = EMMicopyto(500L, 2, 2, (UCF *) testbuf, handle, 16000L);
    nofailcheck("_EMMicopyto()", status, testbuf, handle, 0);
    weirdretchk("_EMMicopyto()", status, testbuf, handle, 0);
    weirdcodechk("_EMMicopyto()", EMM_BADOFFSET, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    ZEROCHECK(frameptr[0], 16384);
    printf("_EMMicopyto() failed OK.\n");
    TESTTAILER();

    /* and another */
    TESTHEADER();
    printf("Calling _EMMicopyto() with element size > 16384 bytes.\n");
    printf("Should fail.\n");
    status = EMMicopyto(2L, 20000, 2, (UCF *) testbuf, handle, 0L);
    nofailcheck("_EMMicopyto()", status, testbuf, handle, 0);
    weirdretchk("_EMMicopyto()", status, testbuf, handle, 0);
    weirdcodechk("_EMMicopyto()", EMM_ELTOOBIG, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    ZEROCHECK(frameptr[0], 16384);
    printf("_EMMicopyto() failed OK.\n");
    TESTTAILER();

    /* and another */
    TESTHEADER();
    printf("Calling _EMMicopyto() with skip size > 32768 bytes.\n");
    printf("Should fail.\n");
    status = EMMicopyto(2L, 2, 40000U, (UCF *) testbuf, handle, 0L);
    nofailcheck("_EMMicopyto()", status, testbuf, handle, 0);
    weirdretchk("_EMMicopyto()", status, testbuf, handle, 0);
    weirdcodechk("_EMMicopyto()", EMM_SKTOOBIG, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    ZEROCHECK(frameptr[0], 16384);
    printf("_EMMicopyto() failed OK.\n");
    TESTTAILER();

    /* test zero-length copy */
    TESTHEADER();
    printf("Calling _EMMicopyto() with zero elements.\n");
    printf("Should succeed.\n");
    status = EMMicopyto(0L, 2, 2, (UCF *) testbuf, handle, 0L);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    ZEROCHECK(frameptr[0], 16384);
    printf("_EMMicopyto() succeeded.\n");
    TESTTAILER();

    /* test zero-length copy differently */
    TESTHEADER();
    printf("Calling _EMMicopyto() with zero-length elements.\n");
    printf("Should succeed.\n");
    status = EMMicopyto(50L, 0, 2, (UCF *) testbuf, handle, 0L);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    ZEROCHECK(frameptr[0], 16384);
    printf("_EMMicopyto() succeeded.\n");
    TESTTAILER();

    /* test skip size of 0 */
    TESTHEADER();
    printf("Calling _EMMicopyto() with zero source and dest skip.\n");
    printf("Should succeed.\n");
    status = EMMicopyto(50L, 2, 0, (UCF *) testbuf, handle, 0L);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    CPYWORDCHECK(frameptr[0], 100);
    ZEROCHECK((frameptr[0] + 100), (16384 - 100));
    printf("_EMMicopyto() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy even same skip, even size */
    TESTHEADER();
    printf("Calling _EMMicopyto() size, skips even,.\n");
    printf("Should succeed.\n");
    status = EMMicopyto(25L, 2, 4, (UCF *) testbuf, handle, 0L);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    status = EMMicopyto(25L, 4, 2, (UCF *) (testbuf + 2), handle, 2L);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    CPYWORDCHECK(frameptr[0], 150);
    ZEROCHECK((frameptr[0] + 150), (16384 - 150));
    printf("_EMMicopyto() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy of size even, skip same odd and size odd, skip same even */
    printf("Calling _EMMicopyto() with size even/skips odd & size odd/skips ");
    printf("even.\nShould succeed.\n");
    status = EMMicopyto(25L, 2, 3, (UCF *) testbuf, handle, 0L);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    status = EMMicopyto(25L, 3, 2, (UCF *) (testbuf + 2), handle, 2L);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    MEMCMP(frameptr[0], testbuf, 125);
    ZEROCHECK((frameptr[0] + 125), (16384 - 125));
    printf("_EMMicopyto() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* test copy of skip same odd, size odd */
    TESTHEADER();
    printf("Calling _EMMicopyto() with skips and size odd.\n");
    printf("Should succeed.\n");
    status = EMMicopyto(25L, 3, 7, (UCF *) testbuf, handle, 0L);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    status = EMMicopyto(25L, 7, 3, (UCF *) (testbuf + 3), handle, 3L);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    CPYWORDCHECK(frameptr[0], 250);
    ZEROCHECK((frameptr[0] + 250), (16384 - 250));
    printf("_EMMicopyto() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* copy entire page in two passes */
    TESTHEADER();
    printf("Calling _EMMicopyto() to copy page in two passes, by words.\n");
    totticks = 0L;
    ticks = get_tick();
    status = EMMicopyto(4096L, 2, 2, (UCF *) testbuf, handle, 0L);
    totticks += (get_tick() - ticks);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    ticks = get_tick();
    status = EMMicopyto(4096L, 2, 2, (UCF *) (testbuf + 2), handle, 2L);
    totticks += (get_tick() - ticks);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    MEMCMP(frameptr[0], testbuf, 16384);
    printf("_EMMicopyto() succeeded, took about %lu ticks.\n", totticks);
    TESTTAILER();

    /* restore destination pattern */
    test_EMMmappage(0, handle, 0);
    FMEMSET(frameptr[0], 0, 16384);

    /* copy entire page, interleaving */
    TESTHEADER();
    printf(
       "Calling _EMMicopyto() to copy page in two passes, skips different.\n");
    status = _EMMicopyto(4096L, 2, 2, (UCF *) testbuf, handle, 0L, 0);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    status = _EMMicopyto(4096L, 2, 2, (UCF *) (testbuf + 2), handle, 8192L, 0);
    TRIPLECHECK("_EMMicopyto()", status, 0, testbuf, handle, 0);
    SRCWORDCHECK(testbuf, 16384);
    test_EMMmappage(0, handle, 0);
    for (loop = 0; loop < 8192; loop += 2)
    {
        if ((*((unsigned int far *)(frameptr[0] + loop)) != loop) ||
            (*((unsigned int far *)(frameptr[0] + loop + 8192)) != (loop + 1)))
        {
            printf("_EMMicopyto() corrupted copied bytes.\n");
            free(testbuf);
            test_EMMfree(handle);
            exit(3);
        }
    }
    TESTTAILER();


    /* fill EMS page with incrementing word pattern */
    test_EMMmappage(0, handle, 0);
    farincwordfill(frameptr[0], 16384, 0);

    /* fill test buffer with a different pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* try a bad copy first */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() with bad offset.\n");
    printf("Should fail.\n");
    status = EMMicopyfrom(5L, 2, 2, handle, 20000L, (UCF *) testbuf);
    nofailcheck("_EMMicopyfrom()", status, testbuf, handle, 0);
    weirdretchk("_EMMicopyfrom()", status, testbuf, handle, 0);
    weirdcodechk("_EMMicopyfrom()", EMM_BADOFFSET, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    ZEROCHECK(testbuf, 16384);
    printf("_EMMicopyfrom() failed OK.\n");
    TESTTAILER();

    /* and another */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() with block that runs off end of EMS.\n");
    printf("Should fail.\n");
    status = EMMicopyfrom(500L, 2, 2, handle, 16000L, (UCF *) testbuf);
    nofailcheck("_EMMicopyfrom()", status, testbuf, handle, 0);
    weirdretchk("_EMMicopyfrom()", status, testbuf, handle, 0);
    weirdcodechk("_EMMicopyfrom()", EMM_BADOFFSET, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    ZEROCHECK(testbuf, 16384);
    printf("_EMMicopyfrom() failed OK.\n");
    TESTTAILER();

    /* and another */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() with element size > 16384 bytes.\n");
    printf("Should fail.\n");
    status = EMMicopyfrom(2L, 20000, 2, handle, 0L, (UCF *) testbuf);
    nofailcheck("_EMMicopyfrom()", status, testbuf, handle, 0);
    weirdretchk("_EMMicopyfrom()", status, testbuf, handle, 0);
    weirdcodechk("_EMMicopyfrom()", EMM_ELTOOBIG, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    ZEROCHECK(testbuf, 16384);
    printf("_EMMicopyfrom() failed OK.\n");
    TESTTAILER();

    /* and another */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() with skip size > 32768 bytes.\n");
    printf("Should fail.\n");
    status = EMMicopyfrom(2L, 2, 40000U, handle, 0L, (UCF *) testbuf);
    nofailcheck("_EMMicopyfrom()", status, testbuf, handle, 0);
    weirdretchk("_EMMicopyfrom()", status, testbuf, handle, 0);
    weirdcodechk("_EMMicopyfrom()", EMM_SKTOOBIG, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    ZEROCHECK(testbuf, 16384);
    printf("_EMMicopyfrom() failed OK.\n");
    TESTTAILER();

    /* test zero-length copy */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() with zero elements.\n");
    printf("Should succeed.\n");
    status = EMMicopyfrom(0L, 2, 2, handle, 0L, (UCF *) testbuf);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    ZEROCHECK(testbuf, 16384);
    printf("_EMMicopyfrom() succeeded.\n");
    TESTTAILER();

    /* test zero-length copy differently */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() with zero-length elements.\n");
    printf("Should succeed.\n");
    status = EMMicopyfrom(50L, 0, 2, handle, 0L, (UCF *) testbuf);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    ZEROCHECK(testbuf, 16384);
    printf("_EMMicopyfrom() succeeded.\n");
    TESTTAILER();

    /* test skip size of 0 */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() with zero source and dest skip.\n");
    printf("Should succeed.\n");
    status = EMMicopyfrom(50L, 2, 0, handle, 0L, (UCF *) testbuf);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    CPYWORDCHECK(testbuf, 100);
    ZEROCHECK((testbuf + 100), (16384 - 100));
    printf("_EMMicopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy even same skip, even size */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() with size, skips even.\n");
    printf("Should succeed.\n");
    status = EMMicopyfrom(25L, 2, 4, handle, 0L, (UCF *) testbuf);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    status = EMMicopyfrom(25L, 4, 2, handle, 2L, (UCF *) (testbuf + 2));
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    CPYWORDCHECK(testbuf, 150);
    ZEROCHECK((testbuf + 150), (16384 - 150));
    printf("_EMMicopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy of size even, skip same odd and size odd, skip same even */
    printf("Calling _EMMicopyfrom() with size even/skips odd & size odd/");
    printf("skips even, offset even.\nShould succeed.\n");
    status = EMMicopyfrom(25L, 2, 3, handle, 0L, (UCF *) testbuf);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    status = EMMicopyfrom(25L, 3, 2, handle, 2L, (UCF *) (testbuf + 2));
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    MEMCMP(frameptr[0], testbuf, 125);
    ZEROCHECK((testbuf + 125), (16384 - 125));
    printf("_EMMicopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* test copy of skip same odd, size odd */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() with skips and size odd.\n");
    printf("Should succeed.\n");
    status = EMMicopyfrom(25L, 3, 7, handle, 0L, (UCF *) testbuf);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    status = EMMicopyfrom(25L, 7, 3, handle, 3L, (UCF *) (testbuf + 3));
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    CPYWORDCHECK(testbuf, 250);
    ZEROCHECK((testbuf + 250), (16384 - 250));
    printf("_EMMicopyfrom() succeeded.\n");
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* copy entire page in two passes */
    TESTHEADER();
    printf("Calling _EMMicopyfrom() to copy page in two passes, by words.\n");
    totticks = 0L;
    ticks = get_tick();
    status = EMMicopyfrom(4096L, 2, 2, handle, 0L, (UCF *) testbuf);
    totticks += (get_tick() - ticks);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    ticks = get_tick();
    status = EMMicopyfrom(4096L, 2, 2, handle, 2L, (UCF *) (testbuf + 2));
    totticks += (get_tick() - ticks);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    MEMCMP(testbuf, frameptr[0], 16384);
    printf("_EMMicopyfrom() succeeded, took about %lu ticks.\n", totticks);
    TESTTAILER();

    /* restore destination pattern */
    FMEMSET((UCF *) testbuf, 0, 16384);

    /* copy entire page, interleaving */
    TESTHEADER();
    printf(
       "Calling _EMMicopyfrom() to copy page in two passes, skips different.\n");
    status = _EMMicopyfrom(4096L, 2, 2, handle, 0L, (UCF *) testbuf, 0);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    status = _EMMicopyfrom(4096L, 2, 2, handle, 2L, (UCF *) (testbuf+8192), 0);
    TRIPLECHECK("_EMMicopyfrom()", status, 0, testbuf, handle, 0);
    test_EMMmappage(0, handle, 0);
    SRCWORDCHECK(frameptr[0], 16384);
    for (loop = 0; loop < 8192; loop += 2)
    {
        if ((*((unsigned int far *)(testbuf + loop)) != loop) ||
            (*((unsigned int far *)(testbuf + loop + 8192)) != (loop + 1)))
        {
            printf("_EMMicopyfrom() corrupted copied bytes.\n");
            free(testbuf);
            test_EMMfree(handle);
            exit(3);
        }
    }
    TESTTAILER();


    /* clean up */
    test_EMMfree(handle);
    free(testbuf);

    return;
} /* end of do_ishortcopy_tests() */

