Алгоритм драйвера

Алгоритм драйвера предельно прост. Работа драйвера заключается в последовательном считывании входных данных, отправке их тестируемому компоненту, получении результата и сравнении его с ожидаемым результатом. При этом если действительный результат не соответствует ожидаемому, то статус драйвера FAIL. В драйвере также необходимо логировать все результаты, результаты каждой итерации записывать в выходной файл и ее статус. Если результат хоть одной итерации FAIL, то драйвер должен продолжать свою работу. Таким образом мы в конце сможем проанализировать все данные и выявить потенциальные дефекты. Сказанное выглядит примерно так:

Bool script_status = true

Matrix M = GenerateInputData()

For i ß 1 to M.rows do

Result expected = GetExptected(M[i])

Result actual = SendRequest(M[i])

Bool status = Compare(expected, actual)

If status = false

Then sctipt_status = false

LogResult(file,i,actual, expected,status)

LogScriptStatus(script_status)

 

Функция GenerateInputData() генерирует входные данные. Далее каждая строка из водных данных считывается и посылается тестируемому компоненту. Предварительно мы генерируем ожидаемый результат для данных входных данных и после сравниваем реальный результат с ожидаемым. В лог-файл мы на каждой итерации записываем номер итерации, реальный и ожидаемый результат и статус. Если на какой-то итерации результаты не совпадают, то наш драйвер будет иметь статус FAIL. Для этого мы определим логическую переменную script_status, которую запишем в конец лог-файла.

 

В качестве примера драйвера и заглушек можно рассмотреть реализацию стека на языке C, причём значения, помещаемые в стек, хранятся не в оперативной памяти, а помещаются в ПЗУ при помощи отдельного модуля, содержащего две функции – записи данных и чтения данных. Формат этих функций таков:

void NV_Read(char *destination, long length, long offset);

void NV_Write(char *source, long length, long offset);

Здесь destination – адрес области памяти, в которую записывается считанное значение, source – адрес области памяти, из которой читается значение, length – длина записываемой области памяти, offset – смещение относительно начального адреса памяти.

Реализация стека с использованием этих функций выглядит следующим образом:

long currentOffset;

void initStack()

{

currentOffset=0;

}

void push(int value)

{

NV_Write((int*)&value,sizeof(int),currentOffset);

currentOffset+=sizeof(int);

}

int pop()

{

int value;

if (currentOffset>0)

{

NV_Read((int*)&value,sizeof(int),currentOffset;

currentOffset-=sizeof(int);

}

}

При выполнении этого кода на реальной системе происходит запись в ПЗУ, однако, если мы хотим протестировать только реализацию стека, изолировав её от реализации модуля работы с памятью, необходимо использовать заглушки вместо реальных функций.

Для имитации работы ПЗУ можно выделить достаточно большой участок оперативной

памяти, в которой и будет производиться запись данных, получаемых заглушкой. Заглушки для функций могут выглядеть следующим образом:

char nvrom[1024];

 

void NV_Read(char *destination, long length, long offset)

{

printf(“NV_Read called\n”);

memcpy(destination, nvrom+offset, length);

}

void NV_Write(char *source, long length, long offset);

{

printf(“NV_Write called\n”);

memcpy(nvrom+offset, source, length);

}

Каждая из заглушек выводит трассировочное сообщение и перемещает переданное значение в память, эмулирующую ПЗУ (функция NV_Write) или возвращает по ссылке значение, хранящееся в памяти, эмулирующей ПЗУ (функция NV_Read).

Схема взаимодействия тестируемого ПО (функций работы со стеком) с тестовым окружением (драйвером и заглушками функций работы с ПЗУ) изображена на рисунке 29.

 

 

 


Рисунок 29 – Схема взаимодействия тестового окружения и тестируемого ПО