Лекция: Разработка драйверов и имитаторов
Драйвер (отлаживающая программа) – это главная программа (функция main на языке С), состоящая из нескольких обращений к тестируемому модулю, каждое из которых реализует один тест и обычно включает следующие действия:
— вывод номера и входных данных теста;
— вызов тестируемого модуля с передачей ему входных данных теста в виде параметров и/или глобальных переменных;
— вывод полученных результатов (или сообщения об итогах их сравнения с эталонным ответом).
Имитатор (заглушка) – это отладочная программа, имитирующая работу модуля, вызываемого из тестируемого модуля. В зависимости от конкретной ситуации можно использовать разные виды заглушек, например:
— пустая подпрограмма, состоящая из заголовка функции и пустого блока (полное отсутствие вызываемой функции, даже если она не нужна для работы тестируемого модуля, недопустимо из-за ошибок трансляции);
— пустая подпрограмма, выводящая сообщение о том, что она отработала, что позволяет проследить последовательность вызовов модулей;
— подпрограмма, возвращающая всегда один и тот же постоянный результат (иногда этого достаточно для проверки правильности функционирования отлаживаемого модуля);
— подпрограмма, возвращающая заранее заготовленный результат, вводимый из файла или хранящийся в массиве;
— подпрограмма, выполняющая имитируемую функцию по упрощенному алгоритму, например, более медленному или с меньшей точностью.
Возможно использование какой-либо комбинации приведенных вариантов.
Заглушка имитирует тестовую ситуацию для отлаживаемого модуля и поэтому зависит от тестов, которые частично или целиком встраиваются в нее в виде констант либо вводятся ею. Для разных тестов могут потребоваться разные заглушки.
Разработка имитаторов — более творческая задача, чем составление драйверов, имеющих обычно простую структуру даже при большом размере.
Далее приведены драйверы и имитаторы для разработанного плана отладки и тестов измененного компилятора С0. Для упрощения драйверов с помощью директивы #include в них вставляются описания глобальных переменных, вынесенные в файл glb.c из текста транслятора (строки 47 -109).
Из модульной структура компилятора С0 (см. приложение 2) видно, что для автономной отладки функции chleks требуется драйвер и имитаторы вызываемых из нее подпрограмм chsim и oshibka (рис. 4).
Драйвер для автономной отладки функции chleks разработан на основе фрагментов функции main компилятора С0. Драйвер читает файл p.c0 с помощью подпрограммы chleks и выводит в файл p.asm полученную последовательность лексем в числовом виде.
/**********************************************/
/* Драйвер chleks */
/**********************************************/
#include <stdio.h>
#include «glb.c»
main()
{
int i;
for (i=0; i<=255; i++) leksim[i]=osh;
leksim['+']=plus; leksim['-']=minus; leksim['*']=umn;
leksim['/']=del; leksim['%']=ost; leksim['=']=prisv;
leksim['<']=men; leksim['>']=bol; leksim['(']=lskob;
leksim[')']=pskob; leksim['{']=flskob; leksim['}']=fpskob;
leksim[',']=zpt; leksim[';']=tchzpt;
vhstr[0]=' '; vhstr[1]='\0'; usim=vhstr;
kolglb=1;
kolim=2;
ef=0;
fvh=fopen(«p.c0»,«r»); /* откpыть входной файл */
fvih=fopen(«p.asm»,«w»); /* откpыть выходной файл */
if ((fvh==NULL) || (fvih==NULL))
printf(«Файлы не откpылись»);
else
{ while (!ef)
{
chleks();
fprintf(fvih,"%d ",leksema);
}
fclose(fvh);
fclose(fvih);
}
}
Имитатор чтения символа — это упрощенная функция chsim, из которой удалены операторы, вставляющие строки исходного текста в файл p.asm:
/**********************************************/
/* Имитатор чтения символа chsim */
/**********************************************/
chsim()
{
if (feof(fvh)) {ef=1; return *usim=EOF;}
return *usim=getc(fvh));
}
Поскольку разработанный тест не содержит ошибок, при его чтении функция oshibka не должна вызываться, и ее имитатор можно было бы сделать пустым. Тем не менее, полезно на всякий случай вставить в имитатор вывод упрощенного сообщения об ошибке, чтобы зафиксировать случаи возможного «обнаружения» несуществующих «ошибок» входного текста из-за ошибок в отлаживаемой программе chleks:
/**********************************************/
/* Имитатор oshibka */
/**********************************************/
oshibka(int n)
{
fprintf(fvih,«Ошибка: ^%d\n»,n);
}
В соответствии с модульной структурой компилятора С0 для тестирования модулей трансляции выражения: virag, operac, vitsk, zopreg, gen_kom и adrper необходим драйвер и имитаторы вызываемых из этих модулей функций: chleks, test, vkluch, pozic и oshibka (рис. 5).
Разработанный для отладки входной текст представляет собой последовательность выражений, заканчивающихся точкой с запятой, и поэтому драйвер циклически обращается к модулю virag, пока не кончится файл p.c0. Перед каждым обращением читается первая лексема очередного выражения.
/**********************************************/
/* Драйвер virag */
/**********************************************/
#include <stdio.h>
#include «glb.c»
main()
{ int i;
kolglb=1; kolim=2;
tabim[1].imja=«x»; tabim[1].vidob=1; /* имя x глобальное */
tabim[2].smesch=2; tabim[2].vidob=1; /* имя y локальное */
ef=0;
fvh=fopen(«p.c0»,«r»); /* откpыть входной файл */
fvih=fopen(«p.asm»,«w»); /* откpыть выходной файл */
if ((fvh==NULL) || (fvih==NULL))
printf(«Файлы не откpылись»);
else
{ while (!ef)
{ chleks();
virag(0L);
}
fclose(fvh);
fclose(fvih);
}
}
В отсутствие функции чтения лексемы входной текст содержит подготовленную вручную последовательность числовых значений лексем, а имитатор функции chleks просто вводит очередное число.
/**********************************************/
/* Имитатор chleks */
/**********************************************/
chleks()
{ fscanf(fvh,"%d ",&leksema);
return leksema;
}
Разработанные тесты: ++x; y++; -x--; --y; x=-y+++5; x=++y+5; y=--x-5; x=y---5; задаются в файле p.asm в виде числовых значений лексем, разделенных пробелами и/или символами новой строки: 18 1 17 1 18 17 4 1 19 17 19 1 17 1 20 4 1 18 3 2 17 1 20 18 1 3 2 17 1 20 19 1 4 2 17 1 20 1 19 4 2 17.
При этом вид ожидаемого объектного кода определен из условия, что x является глобальной переменной, а y — локальной переменной со смещением 2.
Драйвер virag моделирует соответствующую таблицу имен, содержащую под индексом 1 глобальную переменную x, а под индексом 2 — локальную переменную y, имеющую смещение 2:
kolglb=1; kolim=2;
tabim[1].imja=«x»; tabim[1].vidob=1; /* имя x глобальное */
tabim[2].smesch=2; tabim[2].vidob=1; /* имя y локальное */
При обработке разработанного тестового текста обращения к имитатору pozic для поиска позиции (индекса) очередного имени будут происходить в том порядке, в котором в этом тексте расположены имена x и y. Под видом «найденных» индексов имен x и y имитатор pozic будет выдавать размещенные в таком же порядке числа из глобального или статического массива zi.
/***********************************************/
/* Имитатор pozic */
/* позиция имени id в таблице tabim */
/***********************************************/
int nt = 0; /* 1 2 3 4 5 6 7 8 9 10 11 12 N имени */
int zi[20] = { 1,2,1,2,1,2,2,1,1,2, 1, 2 };
/* В тесте x y x y x y y x x y x y */
pozic(int tabl) /* вид таблицы: kolglb/kolim */
{ return zi[nt++] ;
}
Для разработанного теста имитатор vkluch вызываться не должен, но на тот случай, когда это все-таки произойдет из-за ошибок в отлаживаемой программе, в имитаторе предусмотрен вывод соответствующего сообщения.
/***********************************************/
/* Имитатор vkluch */
/* включение имени id в таблицу имен */
/***********************************************/
vkluch()
{
fprintf(fvih,"\n vkluch \n"); /* если по ошибке вызовут */
}
Имитатор oshibka можно использовать такой же, как для отладки chleks. Имитатор test оставлен пустым:
/***********************************************/
/* Имитатор test: проверка лексемы, */
/* сообщение об ошибке и ее нейтрализация */
/***********************************************/
test(long s1, long s2, long n)
/* s1 — множество допустимых лексем (логич. шкала) */
/* s2 — множество дополнительных лексем для пропуска*/
/* n — номер ошибки */
{
}