Системы с приоритетами: конформность, тестирование, композиция
И. Б. Бурдонов, А. С. Косачев {igor, kos}@ispras.ru
Аннотация. В статье представлен подход к моделированию компонентов распределенных систем, взаимодействие которых построено на обработке событий с учетом их приоритетов. Несмотря на широкое использование на практике приоритетной обработки запросов или сообщений, математические модели взаимодействия таких программ чаще всего абстрагируются от приоритетов, вводя излишний недетерминизм в описание их поведения. Предложенный подход пытается избежать этого недостатка за счет определения параллельной композиции, моделирующей взаимодействие такого рода. Основное содержание статьи — построение теории формального тестирования компонентов, использующих приоритеты. В рамках этой теории вводятся понятие безопасного выполнения модели и отношение конформности между моделями, а также рассматриваются вопросы построения наборов тестов, проверяющих конформность.
«Если воняет, то это химия, когда ничего не работает — физика, а если понять нельзя ни слова — математика».
Из «Законов Мэрфи», цитируется по публичной лекции В.И. Арнольда «Сложность конечных последовательностей нулей и единиц и геометрия конечных функциональных пространств».
1. Введение
В существующих теориях тестирования конформности (conformance testing) подразумевается отсутствие приоритетов между действиями, которые тестируемая система может выполнять в данной ситуации [23]. Это называется правилом недетерминированного выбора действий. В то же время для реальных программных и аппаратных систем это правило не всегда адекватно отражает требуемое поведение системы. Рассмотрим несколько примеров.
Выход из дивергенции. Под дивергенцией понимается бесконечная внутренняя активность («зацикливание») системы. Запрос, поступающий извне, может бесконечно долго игнорироваться системой, если он имеет тот же приоритет, что и внутренняя активность. Заметим, что внутренняя активность может быть инициирована предыдущим запросом. Если речь идёт
о составной системе, собранной из нескольких компонентов, то такая внутренняя активность может быть естественным результатом взаимодействия компонентов между собой. И в этом случае для обработки запроса, поступающего в систему (в один из её компонентов) извне, он должен иметь больший приоритет, чем внутреннее взаимодействие.
Выход из осцилляции (приоритет приёма над выдачей). Под осцилляцией понимается бесконечная цепочка выдачи сообщений системой. Для того, чтобы такую цепочку можно было прервать, заставив систему обрабатывать поступающий извне запрос, последний должен иметь больший приоритет, чем выдача сообщений.
Приоритет выдачи над приёмом в неограниченных очередях. Этот обратный пример характерен для неограниченной очереди, используемой в качестве буфера меяеду взаимодействующими системами, в частности, при асинхронном тестировании (тестировании в контексте). Здесь нужно, чтобы выборка из очереди была приоритетней постановки в очередь. В противном случае очередь имеет право только принимать сообщения и никогда их не выдавать. При асинхронном тестировании для входной очереди это означает, что все входные сообщения, посылаемые тестом, не доходят до реализации, бесконечно накапливаясь в очереди. Соответственно, для выходной очереди это означает, что тест может не получать никаких ответных сообщений от реализации, хотя она их выдаёт, поскольку они «оседают» в очереди. Прерывание цепочки действий. Команда «отменить» (cancel) должна останавливать выполнение последовательности действий, инициированной предыдущим запросом, и вызывать цепочку завершающих действий. При отсутствии приоритетов такая команда, даже если она выдана сразу после выдачи запроса, имеет право быть выполнена только после того, как вся обработка закончится, то есть, фактически, ничего не «отменяет». Приоритетная обработка входных воздействий. Если в систему поступает одновременно несколько запросов, то часто требуется их обработка в соответствии с некоторыми приоритетами между ними. Эго обычно реализуется в виде очереди запросов с приоритетами или в виде нескольких очередей запросов с приоритетами между очередями. К этому типу приоритетов относится и обработка аппаратных прерываний в операционной системе. Отсутствие приоритетов в моделях систем не даёт возможности проверять при тестировании выполнение тех требований к системе, которые могут быть выражены только в форме приоритетов. В данной статье предлагается способ введения приоритетов в теорию конформности: семантику взаимодействия и модель системы, отношение конформности, методы генерации тестов и
оператор композиции (сборки составной системы из взаимодействующих между собой компонентов). Теория конформности без приоритетов кратко описана в нашей статье [13], подробное изложение с доказательствами утверждений содержится в диссертации одного из авторов данной статьи [16], теория конформности для класса так называемых Ру5-семантик излагается в книге [15]. Здесь мы сначала повторим основные положения этой теории, а затем модифицируем их для случая приоритетов.
2. Теория конформности без приоритетов
2.1. Семантика взаимодействия и безопасное тестирование
Верификация конформности понимается как проверка соответствия исследуемой системы заданным требованиям. В модельном мире система отображается в реализационную модель (реализацию), требования — в спецификационную модель (спецификацию), а их соответствие — в бинарное отношение конформности. Если требования выражены в терминах взаимодействия системы с окружающим миром, возможно тестирование как проверка конформности в процессе тестовых экспериментов, когда тест подменяет собой окружение системы. Само отношение конформности и его тестирование основаны на той или иной модели взаимодействия.
А, В, С,...сЬ
Рис. 1. Машина тестирования.
Мы будем рассматривать такие семантики взаимодействия, которые основаны только на внешнем, наблюдаемом поведении системы и не учитывают её внутреннее устройство, представленное на уровне модели в виде состояний. В этом случае говорят о тестировании методом «чёрного ящика» или функциональном тестировании. Мы можем наблюдать только такое поведение реализации, которое, во-первых, «спровоцировано» тестом (управление) и, во-вторых, наблюдаемо во внешнем взаимодействии. Такое взаимодействие может моделироваться с помощью, так называемой, машины тестирования [13,15,16,22,23,33]. Она представляет собой «чёрный ящик», внутри которого находится реализация (Рис. 1). Управление сводится к тому, что оператор машины, выполняя тест (понимаемый как инструкция для оператора), нажимает какие-то кнопки на клавиатуре машины, «приказывая» или «разрешая» реализации выполнять те или иные действия, которые могут им наблюдаться. Наблюдения (на «дисплее» машины) бывают двух типов: наблюдение некоторого действия, разрешённого оператором и выполняемого
реализацией, и наблюдение отказа как отсутствия каких бы то ни было действий из числа тех, что разрешены нажатыми кнопками.
Следует подчеркнуть, что при управлении оператор разрешает реализации выполнять именно множество действий, а не обязательно одно действие. Например, при тестировании реактивных систем, основанных на обмене стимулами и реакциями, посылка одного стимула из теста в реализацию может интерпретироваться как разрешение реализации выполнять только одно действие — приём этого стимула. Однако приём тестом ответной реакции должен означать разрешение реализации выдавать любую реакцию как раз для того, чтобы проверить, правильна эта реакция или нет. Мы будем считать, что оператор нажимает одну кнопку, но на кнопке «написано», вообще говоря, не одно действие, а множество разрешаемых действий. Когда происходит наблюдение (действие или отказ) кнопка автоматически отжимается, и все внешние действия считаются запрещёнными. Далее оператор может нажимать другую (или ту же самую) кнопку.
В то же время «кнопочное» множество — это, вообще говоря, не любое подмножество множества всех действий. В вопросе о том, какие множества действий могут разрешаться тестом, а какие нет, среди исследователей существует большое разнообразие точек зрения. Например, для реактивных систем обычно считается, что нельзя (или бессмысленно) смешивать посылку стимулов с приёмом реакций (Ян Тритманс). Но существует и прямо противоположный подход: нельзя «тормозить» выдачу реакций реализацией, поэтому, даже посылая стимул, тест должен быть готов к приёму любой реакции (А. Ф. Петренко в [36]).
Также следует подчеркнуть, что наблюдение отказа возможно не при любой кнопке. И здесь разные исследователи опираются на разные предположения. Для тех же реактивных систем долгое время считалось, что тест может наблюдать отсутствие реакций (quiescence, стационарность), например, по тайм-ауту, но не видит, принимает реализация посланный ей стимул или нет (input refusal, блокировка стимула). С другой стороны, в последние годы появляется всё больше и больше работ, в которых такие блокировки стимулов допускаются или допускаются частично [10-15,26,27,31]. Также и реакции, если они принимаются тестом по разным «выходным каналам», можно принимать не все, а лишь те, которые относятся к одному или нескольким выбранным каналам [26,27].
Итак, семантика взаимодействия определяется тем, какие (в принципе) существуют наблюдаемые действия — алфавит внешних действий L, какие множества действий может разрешать тест — набор кнопок машины тестирования, и для каких из этих кнопок наблюдаемы соответствующие отказы — семейство РсП (L), а для каких нет — семейство ©сП (L). Предполагается, что Рп©=0 и uP u u©=L. Такую семантику мы называем Р/0 -семантикой.
Кроме внешних, наблюдаемых действий реализация может совершать внутренние, ненаблюдаемые (и, следовательно, неразличимые оператором) действия, которые обозначаются символом х. Выполнение таких действий не регулируется оператором — они всегда разрешены. Предполагается, что любая конечная последовательность любых действий совершается за конечное время, а бесконечная последовательность — за бесконечное время. Бесконечная последовательность х-действий («зацикливание») называется дивергенцией и обозначается символом Д. Кроме этого мы вводим специальное, не регулируемое кнопками, действие, которое называем разрушением и обозначаем символом у. Оно моделирует любое запрещённое или недекларированное поведение реализации. Например, в терминах пред- и постусловий, поведение программы определено (постусловием) только в том случае, когда выполнено предусловие обращения к ней. Если же предусловие нарушено, поведение программы считается полностью неопределённым. Семантика разрушения предполагает, в частности, что в результате такого поведения система может быть разрушена.
При тестировании мы должны избегать возникновения ненаблюдаемых отказов (©-отказов), попыток выхода из дивергенции и разрушения. Такое тестирование называется безопасным. Опасность разрушения подразумевается его семантикой. Поясним остальные случаи. В целом их опасность означает, что после нажатия кнопки оператор может не получить никакого наблюдения, и, не зная об этом, не может ни продолжать тестирование, ни закончить его. Если после нажатия кнопки Р возникает ©-отказ Р, оператор не знает, нужно ли ему продолжать ждать наблюдения внешнего действия, разрешённого нажатой кнопкой, или это бессмысленно, поскольку машина стоит. Однако, узнать об остановке машины оператор не может, поскольку это как раз означало бы наблюдение отказа Р. Само по себе возникновение дивергенции не опасно, однако, нажимая после этого любую кнопку, оператор, не наблюдая внешнего действия или Р-отказа (если нажимается Р-кнопка), не знает, случится ли такое наблюдение в будущем, или реализация так и будет бесконечно долго выполнять свои внутренние действия.
Можно также отметить, что из-за внутренних действий нажатие пустой Р-кнопки (кнопки с пустым множеством разрешаемых действий) не эквивалентно отсутствию нажатой кнопки. В обоих случаях все внешние действия запрещены, однако наблюдение отказа означает, что оператор узнаёт об остановке машины, когда она не может выполнять также и внутренние действия. Пустая Р-кнопка не может вызвать разрушение после действия (никакого действия быть не может), но она опасна, если есть дивергенция, как и любая другая кнопка. Пустую ©-кнопку вообще никогда нельзя нажимать, поскольку никакого наблюдения быть не может: все внешние действия запрещены, а отказ не наблюдаем. Поэтому можно считать, что 0г©.
2.2. LTS-модель и трассовая модель
В качестве модели реализации и спецификации мы используем систему помеченных переходов (Labelled Transition System, LTS). LTS — это ориентированный граф с выделенной начальной вершиной, дуги которого помечены некоторыми символами. Формально, LTS — это совокупность S=LTS (Vs, L, Es, s0), где Vs — непустое множество состояний (вершин графа), L — алфавит внешних действий, х — символ внутреннего действия, у —символ разрешения, EsçVsx (Lu{x,y} ) xVs —множество переходов (помеченных дуг графа), s0eVs — начальное состояние (начальная вершина графа). Переход из состояния s в состояние s ' по действию z обозначается s—z—>s '. Обозначим
s—z| =def fs' s—z—>s '. Выполнение LTS, помещённой в «чёрный ящик» машины тестирования, сводится к выполнению того или иного перехода, определённого в текущем состоянии и разрешаемого нажатой кнопкой (х- и у-переходы разрешены при нажатии любой кнопки и при отсутствии нажатой кнопки). Состояние называется стабильным, если в нём нет х- и у-переходов, и дивергентным, если в нём начинается бесконечная цепочка х-переходов (в частности, х-цикл, в том числе, х-петля). Отказ Р порождается стабильным состоянием, в котором нет переходов по действиям из Р.
Для получения трасс LTS достаточно добавить в каждом стабильном состоянии виртуальные петли, помеченные порождаемыми состоянием отказами, а также добавить Д-переходы во всех дивергентных состояниях. После этого рассматриваются все конечные маршруты LTS, начинающиеся в начальном состоянии и не продолжающиеся после Д- или y-перехода. Трассой маршрута считается последовательность пометок его переходов с пропуском х-переходов. Такие трассы мы называем полными или F-трассами, а множество .F-трасс LTS S — полной трассовой моделью или F-моделью, и обозначать F ( S ). /'’-трасса. все отказы которой принадлежат семейству Р, называется Р-трассой. Эго те трассы, которые могут наблюдаться на машине тестирования в Р/0-семантике. Множество всех Р-трасс LTS, то есть проекция её /•’-модели на алфавит, состоящий из всех внешних действий, Р-отказов, символов Д и у, называется P-моделью, соответствующей «взгляду» на реализацию в Р/0-семантике.
2.3. Гипотеза о безопасности и безопасная конформность
Безопасное тестирование, прежде всего, предполагает формальное определение на уровне модели отношения безопасности «кнопка безопасна в модели после Р-трассы». При безопасном тестировании будут нажиматься только безопасные кнопки. Это отношение различно для реализационной и спецификационной моделей. В LTS-реализации I отношение безопасности означает, что нажатие кнопки Р после Р-трассы ст не может означать
попытку выхода из дивергенции (после трассы нет дивергенции), не может вызывать разрушение (после действия, разрешаемого кнопкой), и не может привести к ненаблюдаемому отказу (если это ©-кнопка):
Р safeyAin I after ст =def VueP ст-(и, y)<£F (I) & <j-(A)<£F (I).
P safe in I after ст =def P safejAin I after ст & (Pe© => CT-(P)iF(I) ).
В LTS-спецификации S отношение безопасности отличается только для ©-
кнопок: мы не требуем, чтобы трасса ст не продолжалась безопасным ©-отказом Q, но требуем, чтобы она продолжалась хотя бы одним действием zeQ. Кроме того, если действие разрешается хотя бы одной неразрушающей
0 -кнопкой, то оно должно разрешаться какой-нибудь безопасной кнопкой. Если это неразрушающая P-кнопка, то она же и безопасна. Но если все неразрушающие кнопки, разрешающие действие, являются ©-кнопками, то хотя бы одна из них должна быть объявлена безопасной. Такое отношение безопасности всегда существует: достаточно объявить безопасной каждую неразрушающую кнопку, разрешающую действие, продолжающее трассу. Однако, в целом указанные требования неоднозначно определяют отношение safe by, и при задании спецификации указывается конкретное отношение. Требования к отношению safe by записываются так: VReP VzeL VQe©
1) R safe by S after ст R safejAin S after ст,
2) ЭТе© T safeyAin S after ст & zeT & o-(z)eF(S)
=> ЭРеРи© zeP & P safe by S after ст,
3) Q safe by S after ст => Q safejAin S after ст & 3veQ a-{v)eF {S).
Безопасность кнопок определяет безопасность действий и P-отказов после Р-трассы. P-отказ R безопасен, если после трассы безопасна кнопка R. Действие безопасно, если оно разрешается некоторой кнопкой, безопасной после трассы. Теперь мы можем определить безопасные трассы. Р-трасса безопасна, если 1) модель не разрушается с самого начала (сразу после включения машины ещё до нажатия первой кнопки), то есть в ней нет трассы (у), 2) каждый символ трассы безопасен после непосредственно
предшествующего ему префикса трассы. Множества безопасных трасс реализации I и спецификации S обозначим Safeln (I) и SafeBy (S), соответственно.
Требование безопасности тестирования выделяет класс безопасных реализаций, то есть таких, которые могут быть безопасно протестированы для проверки их конформности или неконформности заданной спецификации. Этот класс определяется следующей гипотезой о безопасности: реализация I безопасна для спецификации S, если 1) в реализации нет разрушения с самого начала, если этого нет в спецификации, 2) после общей безопасной трассы реализации и спецификации любая кнопка, безопасная в спецификации, безопасна после этой трассы в реализации:
I safe for S =def (<y)gF(S) =s> <y)gF(I))
& V n e Safe By (S) rSafeln (I) V P ePu©
(P safe by S after ct => P safe in I after ct).
Следует отметить, что гипотеза о безопасности не проверяема при тестировании и является его предусловием. После этого можно определить отношение (безопасной) конформности: реализация I безопасно конформна (или просто конформна) спецификации S, если она безопасна и выполнено тестируемое условие: любое наблюдение, возможное в реализации в ответ на нажатие безопасной (в спецификации) кнопки, разрешается спецификацией:
I saco S =def I safe for S
& VneSafeliy (S) rSafeln (I) VP safe by S after ct
obs (ct, P, I) cobs (a, P, S),
где obs(a, P,T) =def {u I CT-(u)eF(T) & (ueP v u=P & PeP) } —
множество наблюдений, которые можно получить над моделью Т при нажатии кнопки Р после трассы ст.
2.4. Параллельная композиция и генерация тестов
Взаимодействие двух систем моделируется в LTS-теории оператором параллельной композиции. Мы используем оператор композиции, аналогичный тому, который определяется в алгебре процессов CCS (Calculus of Communicating Systems) [32,34]. Будем считать, что для каяедого внешнего действия z определено противоположное действие z так, что JL=z. Например, посылке стимула из теста соответствует приём теста в реализации, а выдаче реакции реализацией соответствует приём этой реакции в тесте. Параллельное выполнение двух LTS в алфавитах А и В понимается так, что переходы по противоположным действиям z и z, где zeA и zeВ, выполняются синхронно, то есть, в обеих LTS одновременно, причём в композиции это становится х-переходом. Такие действия называются синхронными. Остальные внешние действия zeA\B и zeB\A, а также символы х и у называются асинхронными. Переход по такому символу выполняются в одной из LTS при сохранении состояния другой LTS. Результатом композиции двух LTS I и Т становится LTS 1^Т в алфавите А^В =def (А\В) и (В\А). Её состояния — это пары состояний it LTS-операндов, начальное состояние — это пара начальных состояний, а переходы порождаются следующими правилами вывода:
(1) ze{x,y}uA\B & i—z—>i ' □ it—z—>i't,
(2) ze{x,y}uB\A & t—z—>t' □ it—z—»it',
(3) zeAnB & i—z—>i ' & t—z—>t' □ it—x—>i't'.
Тестирование понимается как замкнутая композиция LTS-реализации I в алфавите А и LTS-теста Т в противоположном алфавите В=А. Для
обнаружения отказов в тесте (но не в реализации!) допускаются специальные 9-переходы, которые срабатывают тогда и только тогда, когда никакие другие переходы не могут выполняться:
(4) t—0—>t' & Deadlock {i,t) □ it—x—>it',
где Deadlock (i, t) = i—x | & i—у | & t—x | & t—у |
& (VzeAr^B i—z| v t—zj ).
Мы будем предполагать, что в тесте также нет разрушения (требование t—у | всегда выполнено).
Поскольку алфавиты реализации и теста противоположны, композиционный алфавит пуст и в композиционной LTS есть только х- и у-переходы. При безопасном тестировании у-переходы недостижимы. Выполнению теста соответствует прохождение х-маршрута, начинающегося в начальном состоянии композиции 1=^Т. Тест заканчивается, когда достигается терминальное состояние теста. Каждому такому терминальному состоянию назначается вердикт pass или fail. Реализация проходит тест, если состояния теста с вердиктом fail недостижимы. Реализация проходит набор тестов, если она проходит каждый тест из набора. Набор тестов значимый, если каждая конформная реализация его проходит; исчерпывающий, если каждая неконформная реализация его не проходит; полный, если он значимый и исчерпывающий. Задача заключается в генерации полного набора тестов по спецификации.
Обычно ограничиваются, так называемыми, управляемыми тестами, то есть тестами без лишнего недетерминизма. Для этого множество внешних действий, для которых определены переходы в данном состоянии теста, должно быть одним из «кнопочных» множеств Р/©-семантики (точнее, множеством противоположных действий, поскольку при композиции CCS тест определяется в противоположном алфавите). Оператор, исполняя тест, однозначно определяет, какую кнопку ему нужно нажимать в данном состоянии теста. Если это P-кнопка, то в состоянии должен быть также определён 9-переход.
Полным набором всегда является набор всех примитивных тестов. Примитивный тест строится по одной выделенной безопасной Р-трассе спецификации. Для этого сначала в трассу перед каждым P-отказом R вставляется кнопка R, а перед каждым действием z — какая-нибудь безопасная (после префикса трассы) кнопка Р, разрешающая действие z. Для различения кнопок и отказов (и то и другое — подмножества внешних действий) мы будем кнопки заключать в кавычки и писать “Р”, а не просто Р. Безопасность трассы гарантирует безопасность кнопки R и наличие такой безопасной кнопки Р. Выбор кнопки Р может быть неоднозначным, то есть по одной безопасной трассе спецификации можно сгенерировать, вообще говоря, множество разных примитивных тестов. После расстановки кнопок
получается последовательность, которая во втором разделе статьи называется Р/0-историей. По ней и строится LTS-тест (Рис. 2). Его состояниями становятся расставленные кнопки, начальное состояние — это первая в трассе кнопка, символы переходов из состояния-кнопки — это действия, противоположные тем, которые могут наблюдаться после нажатия этой кнопки, или символ 9, если это P-кнопка. Если это не последняя кнопка, то один переход ведёт в состояние, соответствующее следующей кнопке. Остальные переходы ведут в терминальные состояния. Вердикт pass назначается тогда, когда соответствующая Р-трасса есть в спецификации, а вердикт fail — когда нет. Такой вердикт соответствует строгим тестам, которые, во-первых, значимые (не ловят ложных ошибок) и, во-вторых, не пропускают обнаруженных ошибок. Любой строгий тест можно заменить на объединение примитивных тестов, которое обнаруживает те же самые ошибки.
ст=(А, b, с )=>встав ляем .безопасные кнопки=>
=>(“А”,А,“В”,Ь,“С”,с) такие, что:
А, ВеР, Сев, be В, сеС.
Внешнее действие имеет индекс «;;орошо», если оно есть в спецификации после префикса трассы; иначе — индекс «пло;;о». Пунктиром показаны взаимоисключающие 9-переходы, ведущие из одного состояния.
ИнДеКСЫ «::орошо^ И «пло;;о» означают наличие или отсутствие продолжения префикса трассы соответствующим Р-отказом.______________
Рис. 2. Примитивный тест для безопасной R-трассы а.
Теперь рассмотрим две проблемы, связанные с применением теории тестирования конформности на практике.
2.5. Недетерминизм и глобальное тестирование
Как уже было сказано, в каждый момент времени реализация может выполнять любое определённое в ней и разрешённое оператором внешнее действие, а также определённые и всегда разрешённые внутренние действия (мы избегаем разрушения при безопасном тестировании). Если таких действий несколько, выбирается одно из них недетерминированным образом. Здесь предполагается, что недетерминизм поведения реализации — это явление того 32
pass
уровня абстракции, которое определяется нашими тестовыми возможностями по наблюдению и управлению, то есть семантикой взаимодействия. Иными словами, поведение реализации недетерминировано, поскольку оно зависит от неких не учитываемых нами факторов — «погодных условий», которые определяют выбор выполняемого действия детерминировано.
Для того, чтобы тестирование могло быть полным, мы должны предположить, что любые погодные условия могут быть воспроизведены в тестовом эксперименте, причём для каждого теста. Если такая возможность есть, тестирование называется глобальным [33]. Мы абстрагируемся от количества вариантов погодных условий. Здесь нам важна только потенциальная возможность проверить поведение системы при любых погодных условиях и любом поведении оператора. Конечно, на практике используется только конечное число прогонов каждого теста. Без дополнительных условий мы не можем быть уверены, что провели тестовые испытания каждого теста для всех возможных погодных условий. Возможны различные решения этой проблемы. Одно из них — специальные тестовые возможности по управлению погодой. Для этого мы должны выйти за рамки модели, которая как раз и абстрагировалась от второстепенных деталей внешних факторов, то есть от погоды. Тем самым, тестирование становится зависящим не только от спецификации, но и от реализационных деталей, от того, что можно назвать операционной обстановкой, в которой работает реализация. Для каждого варианта такой операционной обстановки мы будем вынуждены создавать свой набор тестов. Тем не менее, в некоторых частных случаях на этом пути можно получить практические выгоды.
Другое решение — специальные реализационные гипотезы. Для конечного числа прогонов теста предполагают, что, если реализация ведёт себя правильно при некоторых погодных условиях, то она будет вести себя правильно при любых погодных условиях [6].
Третье решение основано на том, что нам известно распределение вероятностей тех или иных погодных условий. В этом случае тестирование оказывается полным с той или иной вероятностью [19].
Близкое к этому четвёртое решение предполагает, что в каждой ситуации (после трассы) возможно лишь конечное число погодных условий (с точностью до эквивалентности) и существует такое число Ы, что после N прогонов теста гарантированно будет проверено поведение реализации при всех возможных в этой ситуации погодных условиях [21,32].
Наконец, существует и более радикальное решение — просто запретить недетерминизм реализации, то есть реализационная гипотеза ограничивает класс реализаций только детерминированными реализациями. При всей своей наивности, это достаточно распространённый практический приём [35] (он применялся и в ИСП РАН в рамках системы ишТЕ8К). Обоснованием может
служить то, что во многих случаях заранее известно, что интересующие нас реализации детерминированы.
2.6. Бесконечность полного набора тестов
На практике используются только конечные наборы конечных (по времени выполнения) тестов. Поскольку тесты конечные, полный набор, как правило, содержит бесконечное число тестов (полный набор конечен только для моделей с конечным поведением, то есть конечным числом трасс; в частности, в LTS-спецификации не должно быть циклов). Возможны различные решения этой проблемы. В конечном счёте все они сводятся к специальным реализационным гипотезам. Такие гипотезы, по сути, предполагают ровно то, что хотелось бы «доказать»: если реализация ведёт себя правильно на тестах данного конечного набора, то она будет вести себя правильно на всех тестах полного набора. Обоснованием может служить некоторое (не важно как полученное) «знание» о том, как могут быть устроены тестируемые реализации (тестируем не все возможные реализации, а только такие). На классе всех реализаций такие конечные наборы тестов будут только значимыми (не ловят ложных ошибок), а полными — только на подклассе, определяемом реализационной гипотезой.
Конечный набор тестов строится по тому или иному критерию покрытия, чтобы проверить все интересующие нас классы ситуаций (ошибок) [24,25,37]. Теоретически конечный набор можно получить фильтрацией по критерию покрытия перечислимого полного набора. Поэтому теория конформности должна быть развита до уровня алгоритмов перечисления полного набора. Однако на практике обычно используются более прямые методы построения нужного конечного набора. Достаточно общий подход сводится к тому, что вместо исходной спецификационной модели используется более грубая, так называемая, тестовая модель. Тестовая модель — это результат факторизации исходной LTS-спецификации по отношению эквивалентности переходов, что обычно сводится к эквивалентности состояний и/или действий [1]. Иногда при факторизации исчезает недетерминизм, что заодно решает и эту проблему. Разумеется, чтобы такой подход был оправданным, нужны мотивированные реализационные гипотезы о том, что ошибки, возможные в реализации, обнаруживаются при тестировании по факторизованной спецификации (вообще по конечному набору, удовлетворяющему критерию покрытия). Примером практического тестирования может служить тестирование конечного автомата по спецификации, заданной также в виде конечного автомата [3,4,6,18,28,29]. Если у нас есть специальная операция, позволяющая достоверно и напрямую опросить текущее состояние реализации (status message), то, как известно, полное тестирование сводится к обходу графа переходов автомата и применению операции опроса в каждом проходимом состоянии [3,6-9,20,29]. Обход графа переходов используется также в случае тестирования методом «чёрного ящика», когда состояния реализации не
видны. Но здесь для полноты тестирования требуются реализационные гипотезы, компенсирующие отсутствие тестовой возможности достоверного опроса состояний [3,4,6]. Предполагается, что число состояний реализации не превосходит число состояний спецификации (с точностью до эквивалентности состояний) или превосходит не более, чем на заранее известную величину [17,18,29,30]. Этот подход переносится и на общий случай ЬТ8 для реактивных систем [5]. В частности, когда используется, так называемое, стационарное тестирование, при котором стимулы подаются в реализацию только в её стационарных состояниях (в этом случае также снимается проблема торможения реакций) [2].
3. Теория конформности с приоритетами
3.1. Предикаты на переходах ЬТЭ-модели
Независимо от наличия или отсутствия приоритетов семантика взаимодействия предполагает, что выполняться может только то действие, которое определено в реализации и разрешено оператором машины тестирования. Если приоритетов нет, то выполняться может любое определённое и разрешённое действие, и выбор выполняемого действия не детерминирован. Наличие приоритетов означает, что не все определённые и разрешённые действия могут выполняться, то есть выполнимость действия зависит также от того, какие ещё действия определены и/или разрешены. Эту зависимость можно изобразить в виде предиката от множества разрешённых действий, который назначается переходу ЬТ8-модели. Поскольку для перехода в—2—>з известно его пресостояние б, а для этого состояния б известно, какие ещё переходы в нём начинаются, предикат на переходе можно считать не зависящим от множества определённых (в состоянии б) действий. Иными словами, переходы по одному и тому же действию, ведущие из разных состояний, могут иметь разные предикаты.
ЬТ8-модель с приоритетами — это ЬТ8, алфавит которой — декартовое произведение алфавита внешних действий и множества предикатов на алфавите внешних действий П={7г: П (Ь) -^Воо1]:
8=ЬТЗ (У5, ЬхП, Е5, з ). Переход в—2 ,71—>з ' может выполняться только тогда, когда оператор разрешает такое множество внешних действий Р.сЬ. что 2еИи {х, у} и л (К) =£гие. Если есть несколько выполнимых действий, выполняется одно из них, выбираемое, по-прежнему, недетерминированным образом.
Предикат можно понимать как булевскую функцию от булевских переменных т.1г7.2,—, взаимно-однозначно соответствующих внешним действиям из алфавита Ь. Например, для предиката 7г=а&-1^с переход в—г,п^-Б' может выполняться только тогда, когда оператор разрешил такое множество внешних действий И, что 2еРи {х,у} & (аеР.&Ь^Р.-/сеР.). Это означает.
что действие z — это внутреннее действие, разрушение или внешнее действие, разрешённое оператором, а также выполнено хотя бы одно из двух условий: 1) оператор разрешил действие а и не разрешил действие Ь, 2) оператор разрешил действие с.
Итак, в общем случае предикат — это булевская функция от множества разрешённых действий. Можно отметить важный частный случай, когда предикат зависит только от разрешённых и определённых внешних действий. Иными словами, предикат на переходе s—z, я—>s ' не зависит от тех булевских переменных, которые соответствуют внешним действиям, по которым нет переходов из состояния s. Эго означает, что выполнимость перехода зависит только от того, разрешено ли действие z, и какие ещё действия определены в состоянии s и разрешены оператором. В этом случае реализацию не интересуют (она «не видит») те действия, которые оператор разрешает, но они всё равно не могут выполняться, поскольку не определены в текущем состоянии реализации. Нажимая кнопку, оператор как бы «подсвечивает» некоторые действия реализации, определённые в её текущем состоянии, и выполнимость перехода по каждому из них определяется соответствующим предикатом от множества «подсвеченных» действий.
Предикат л как булевская функция от булевских переменных-действий может быть представлен в виде совершенной дизъюнктивной нормальной формы (СДНФ) 7l=T|iVr|2V..., Где T|i=Xii&Xi2&..., Xij=Zj ИЛИ Xij=-iZj, И Zj пробегает множество всех внешних действий. Тогда переход s—z, 7i—>s ' можно заменить на множество кратных переходов с предикатами-дизъюнктами s—z, r|i—>s '. В свою очередь дизъюнкту r|i взаимнооднозначно соответствует множество Pi тех действий, ДЛЯ которых Xij = Zj. При композиции это множество является множеством действий, разрешаемых партнёром. В случае, когда таким партнёром является тест для заданной Р/0-семантики, эти множества разрешаемых действий соответствуют кнопкам из Ри@. Тем самым, при тестировании мы можем считать, что на переходах написаны не произвольные предикаты, а кнопки s—z, Р —>s . Когда нажимается некоторая кнопка Р1; выполняться могут только переходы вида s—z, Pi—>s ', где z е Р ■ и {х, у}. Такой переход от LTS с предикатами к LTS с кнопками аналогичен переходу от расширенных автоматов (EFSM — Extended Finite State Machine) к обычным автоматам (FSM).
3.2. Остановка и дивергенция
Машина без приоритетов останавливается в стабильном состоянии (состоянии без х- и у-переходов), в котором нет переходов по разрешённым внешним действиям. Если есть приоритеты, то меняется, прежде всего, само понятие стабильности. Оно становится условным: состояние стабильно, если для всех переходов из этого состояния их предикаты от пустого множества разрешённых внешних действий ложны л (0) =false. Соответственно 36
меняется условие остановки машины: машина стоит, если при разрешённом множестве внешних действий Р для всех переходов из этого состояния их предикаты ложны л (Р) =/я/«е.
Здесь мы должны уточнить, что происходит, когда кнопка отжимается. Для машины без приоритетов кнопка автоматически отжимается при любом наблюдении действия или отказа. После действия машина может выполнять любые т-переходы (а также у-переход), но после отказа машина стоит, поскольку отказ происходит в стабильном состоянии, в котором нет х- и у-переходов. Однако для машины с приоритетами отжатие кнопки меняет множество разрешённых действий (если только не была нажатой пустая Р-кнопка, дающее единственное наблюдение пустого отказа). После наблюдения реализация начинает выполнять т-переходы с приоритетом л (0) =&ие. Заметим, что таким наблюдением может быть не только действие, но и отказ. Причина этого в том, что отказ Р означал невозможность выполнения разрешённых внешних действий а также х- и у-переходов, поскольку их
предикаты стали ложны л (Р) =/а1не. После отжатия кнопки Р множество разрешённых внешних действий пусто и теперь могут выполняться х- и у-переходы с предикатами л (0) =&ие. Далее оператор может снова нажать ту же кнопку (но без гарантии повторного наблюдения того же отказа, если реализация сменила состояние по х-переходам) или другую кнопку.
Если допускается переключение кнопок, то есть нажатие второй кнопки, не дожидаясь наблюдения по первой кнопке, то это интерпретируется как отжатие первой кнопки, а потом нажатие второй кнопки. Мы будем считать, что «в промежутке» между двумя кнопками создаётся ситуация, когда ни одна кнопка не нажата, и реализация может выполнять х- и у-переходы с предикатами л (0) =&ие. Общая парадигма здесь заключается в том, что ситуация отсутствия тестового воздействия возникает всегда при включении машины (до нажатия первой кнопки), после любого наблюдения и между двумя тестовыми воздействиями. Более подробно переключение кнопок рассматривается в следующем подразделе.
Мы уже говорили, что даже для машины без приоритетов проблема дивергенции не в ней самой по себе, а в выходе из неё. При наличии приоритетов, если внешнее воздействие имеет больший приоритет, чем внутренняя активность, дивергенция прекращается. Теперь выполнимость х-действий зависит от нажатой кнопки, и мы можем косвенно управлять ими и, следовательно, дивергенцией. Тогда можно говорить о выполнимой дивергенции: при одной нажатой кнопке (или когда нет нажатой кнопки) все х-действия бесконечной цепочки выполнимы, а при другой — нет и, следовательно, нет «зацикливания». Выйти из дивергенции, которая начинает выполняться после кнопки А, можно с помощью кнопки В, при которой дивергенция не выполнима. Заметим, что для этого требуется переключение кнопок, то есть нажатие кнопки без наблюдения (которого может не быть).
Единственный случай, когда из дивергенции нельзя гарантированно выйти, — это когда дивергенция выполнима при нажатии любой кнопки.
3.3. Переключение кнопок
В машине без приоритетов кнопку можно нажимать либо после включения машины, либо после того, как произошло наблюдение по предыдущей кнопке. Иными словами, запрещается переключать кнопки без наблюдения, отжимая одну кнопку и нажимая другую. Этот запрет объясняется тем, что, если приоритетов нет, возможность переключения кнопок не увеличивает мощность тестирования. Действительно, если была нажата кнопка Р, а потом без наблюдения нажата другая кнопка 0. (а кнопка Р отжата), то в этом интервале времени реализация могла выполнять только т-действия. Но т-действия всегда разрешены, поэтому реализация могла бы выполнять их и в том случае, когда вместо кнопки Р сразу нажималась кнопка 0. (а второй раз, естественно, не нажималась). Тем самым, любое поведение, которое можно наблюдать в первом случае, можно было бы наблюдать и во втором случае.
При наличии приоритетов переключение без наблюдения необходимо для полноты тестирования, поскольку различные множества разрешённых действий по-разному влияют на выполнение т-действий (т-переходы тоже могут иметь предикаты), что приводит к внешне различимым поведениям. Например, если в реактивной системе приём стимула приоритетнее выдачи реакций и т-действий, последние выполняются только тогда, когда реализация не может принять стимул, посылаемый ей тестом. На Рис. 3 показан пример, где для получения тестом реакции ! у после стимула ? а нельзя сразу посылать этот стимул (тогда после него будет реакция ! х), а нужно сначала послать стимул ?Ь, а потом переключить кнопку { ?Ь} на кнопку { ?а}, послав тем самым стимул ?а. Если реализация принимает стимул ?Ь, то переключение нужно успеть сделать до приёма стимула ?Ь. Если же реализация блокирует стимул ?Ь (нет пунктирного перехода), то можно «не торопиться»; если блокировка {?Ь} наблюдаема, можно сначала её дождаться, а потом послать стимул ?а.
Тем не менее, в пользу запрета на переключение кнопок имеются разумные аргументы и в случае наличия приоритетов. Дело в том, что переключение кнопок позволяет «обходить» ненаблюдаемый отказ: если оператор
переключает 0-кнопку Р на (любую) другую кнопку (¿, то возникновение ненаблюдаемого отказа Р не препятствует такому переключению (как на О, когда нет пунктирного перехода по стимулу ?Ь, а блокировка {?Ь} не наблюдаема). Другое дело, что, если возможен отказ Р, то при безопасном тестировании мы не можем нажимать кнопку Р без последующего переключения на другую кнопку, то есть с ожиданием наблюдения (на О кнопку {?Ь} всегда нужно переключать на кнопку {?а} или какую-то другую). Тем самым, если можно переключать кнопки, условие безопасности
0 -кнопок более сложное (ниже мы его подробно рассмотрим). Если переключений кнопок нет, тестирование выглядит более привычно как чередующаяся последовательность тестовых воздействий (нажимается кнопка) и наблюдений. Кроме того, в этом случае к работе оператора предъявляется меньше временных требований.
3.4. Временные ограничения на работу оператора (теста)
Введение приоритетов усложняет работу оператора, налагая более сложные требования по времени. Если приоритетов нет, то оператор должен уметь достаточно быстро нажимать кнопку после включения машины или после предыдущего наблюдения. Заметим, что если оператор не успевает достаточно быстро нажать кнопку, ничего страшного не случится, поскольку машина успеет выполнить только одно или несколько х-действий, которые (в машине без приоритетов) она может выполнить и в том случае, когда кнопка была нажата немедленно. Иными словами, мы требуем, чтобы оператор мог работать быстро, но не заставляем его всегда работать быстро.
Если приоритеты есть, то возможность наблюдения тех или иных поведений реализации требует не только достаточно высокой скорости работы оператора, но также достаточно медленной, средней и т.д. В примере на Рис. 4 стимул ?а может приниматься в трёх состояниях 1, 2 и 3, но реакции после этого различны: !х, !у или ! 2. Эти состояния связаны х-переходами, которые
выполнимы только, если тест не посылает стимул ?а. Поэтому реакция ! х будет наблюдаться только, если оператор быстро нажмёт кнопку { ? а}, реакция ! 2 — только если оператор не будет торопиться, а реакция ! у — только при средней скорости работы.
Если есть переключение кнопок, то такое переключение также нужно уметь делать с различными интервалами времени, чтобы «заставить» реализацию проходить нужное число х-переходов между двумя кнопками.
1 т, -i?a т, -i?a 3
la, true la, true
1 Г 1 f Л
II < \ о
! у, true ! z, true
1 Г 1 Г 1 г
• 1 > •
Рис. 4. Модель, поведение которой зависит от скорости нажатия кнопок.
Таким образом, для машины с приоритетами следует учитывать временные задержки, которые делает оператор между наблюдением и последующим нажатием кнопки или между двумя нажатиями кнопок при их переключении без наблюдения. Мы можем считать, что в погодные условия включены также те факторы, которые влияют на «свободу воли» оператора, определяя те или иные временные задержки при нажатии кнопок. Это согласуется с тем, что оператор должен моделировать любую скорость работы окружения. Работа оператора моделирует выполнение тестовой программы на компьютере. Такая программа недетерминирована только на некотором уровне абстракции, когда мы отвлекаемся от других программ или аппаратуры, влияющих на её поведение.
3.5. Истории
Если приоритетов нет, возможность наблюдения действия после некоторой предыстории взаимодействия не зависит от того, какая именно нажимается кнопка, разрешающая это действие. При наличии приоритетов это становится важным, поскольку различным кнопкам соответствуют различные множества разрешённых действий, и при нажатии одной кнопки предикат может оказаться истинным, и действие может наблюдаться, а при нажатии другой — ложным, и действие не может наблюдаться. Поэтому теперь нужно запоминать не только наблюдения, но также те кнопки, которые нажимал оператор. Тем самым, результатом тестового эксперимента становится последовательность действий, отказов и кнопок. Такую последовательность мы будем называть историей. Чтобы в истории отличить кнопку от отказа (и то и другое — подмножество внешних действий), мы будем кнопку заключать в кавычки и писать “Р”, а не просто Р. Если не ограничиваться только безопасным тестированием, то мы должны включить в истории также разрушение и дивергенцию, но после них история не может продолжаться, аналогично трассам. Очевидно, что в истории каждому внешнему действию 2 непосредственно предшествует кнопка “Р”, разрешающая это действие геР. а каждому отказу И — Р-кнопка “К”. Могут или не могут идти две кнопки подряд, зависит от того, разрешено или запрещено переключение кнопок.
Для заданной Р/0-семантики истории будем называть Р/©-историями. Определим их более формально.
Рассмотрим LTS с предикатами S. Для множества разрешённых действий Р переход s—z, 71—>s ' будем называть Р-выполнимым, если его предикат истинен л (Р) =true. Будем говорить, что для множества разрешённых действий Р т-маршрут Р-еыполним, если все его переходы Р-выполнимы.
Пустая Р/0-история заканчивается в состояниях, достижимых из начального состояния по 0-выполнимым т-маршрутам, то есть, когда после включения машины не нажата никакая кнопка. Пусть Р/0-история ст заканчивается во множестве состояний S after ст. Рассмотрим различные продолжения этой Р/0-истории. Мы будем предполагать, что Р/0-история не заканчивается разрушением или дивергенцией, поскольку после дивергенции и разрушения нет продолжений.
Продолжение кнопкой Р, где РеРи©. Если допускается переключение кнопок, такое продолжение всегда возможно. Если переключения кнопок нет, Р/0-история не должна заканчиваться кнопкой. Переключение интерпретируется как отжатие первой кнопки, а потом нажатие второй кнопки. Поэтому сначала реализация может выполнить любой 0-выполнимый т-маршрут, начинающийся в состоянии из S after ст, а затем продолжить выполнение любым P-выполнимым т-маршрутом. Множество концов таких маршрутов и будет множеством состояний S after ст-(“Р”). Заметим, что, если история не заканчивалась на кнопку, то концы всех 0-выполнимых т-маршрутов уже входят в S after ст.
Продолжение внешним действием z. Такое продолжение возможно только в том случае, когда сама Р/0-история имеет вид ст-(“Р”), то есть заканчивается кнопкой Р, разрешающей это действие zeP. Наблюдение действия z происходит, когда совершается Р-выполнимый переход по z из состояния
после предшествующей P/0-ИСТОриИ, ТО есть перехода S Z,7T—>s', где
se (S after ст-<“Р”» и 7i (Р) =true. В результате такого перехода кнопка автоматически отжимается, и далее могут выполняться 0-выполнимые т-маршруты до тех пор, пока не возникнет разрушение, пока не будет нажата кнопка (та же самая или другая), или пока оператор не выключит машину, заканчивая сеанс тестирования. Множество концов этих т-маршрутов и является множеством S after ct-(“P”,z).
Продолжение P-отказом Р. Такое продолжение возможно только в том случае, когда сама Р/0-история имеет вид ст-(“Р”). Отказ Р возникает в таком состоянии se (S after ст-(“Р”)), в котором выполнено условие остановки машины: для каждого перехода (по любому действию, включая х и у) s—z, 71—>s ' должно быть 7г (Р) =false. После отказа кнопка
отжимается и реализация может выполнить 0-выполнимый т-маршрут, начинающийся в одном из состояний, где наблюдался отказ. Множество концов этих т-маршрутов и является множеством
S after ст-(“Р”, Р).3аметим, что состояния, где наблюдался отказ, тоже входят в это множество (для пустого т-маршрута).
Продолжение разрушением у. Такое продолжение возможно только в том случае, когда в некотором состоянии se (S after ст) переход s—у, n—>s Р-еыполнимым, если Р/0-история заканчивается кнопкой Р (наблюдения ещё не было, и продолжает действовать кнопка Р), или 0-выполним в противном случае (после наблюдения не действует никакая кнопка). Поскольку после разрушения нет продолжения, нас не интересует множество состояний после такого продолжения.
Продолжение дивергенцией Д. Поскольку опасна не сама дивергенция, а попытка выхода из неё, нас будет интересовать только такая дивергенция, которая выполнима при нажатой кнопке Р. Такая дивергенция возникает после Р/0-истории вида ст-(“Р”), если есть бесконечный P-выполнимый х-маршрут, начинающийся в состоянии из S after ст-(“Р”) (очевидно, достаточно считать, что маршрут начинается в состоянии из S after ст). В этом случае символ Д будет продолжать Р/0-историю после кнопки Р. Поскольку после дивергенции нет продолжения, нас не интересует множество состояний после такого продолжения.
Теперь аналогично трассам определим полные истории или F-ucmopuu как Р/0-истории для Р=П (L) и, соответственно, 0=0, когда любое подмножество внешних действий является P-кнопкой. Множество F-историй LTS S — обозначим так же, как множество F-трасс. — F (S), поскольку в дальнейшем мы будем рассматривать только истории, а не трассы. Теперь Р/0-история LTS — это такая её F-история, в которой встречаются кнопки только из семейств Р и ©, а отказы — это только Р-отказы.
3.6. Безопасность и конформность без переключения кнопок
Поскольку выполнимость переходов LTS-модели с приоритетами зависит от предикатов на этих переходах, меняются отношения безопасности кнопок в реализации (safe in) и спецификации (safe by).
Если нет переключения кнопок, то отношения safe in и safe by определяются почти так же, как для машины без приоритетов. Изменения заключаются в том, что вместо Р-трасс рассматриваются Р/0-истории, безопасность или опасность кнопки определяется только после Р/0-истории, не заканчивающейся кнопкой, продолжение внешним действием зависит от кнопки, дивергенция возможна лишь после кнопки, разрушения не должно быть не только после действия, но также после отказа (для P-кнопки) и сразу после нажатия кнопки.
Определение отношения безопасности в реализации без переключения кнопок:
Р safe^in I after ст =<jef ст-(“P”,y)g.F(I) & VueP ст-(“Р”, u,y)g.F(I)
& (PeP =s> ct-<“P”, P,y)gF(I) ).
P safeyAin I after ст =def P safe,in I after ст &_ст££1,Д)&FJJ±.
P safein I after ст =def P safe, in I after ст & (Ре©=>ст(“Р”, P)gF (I) ). Требования к отношению безопасности в спецификации без переключения кнопок: VReP VzeL VQe©
1) R safe ¡by S after ст R safejAin S after ст,
2) ЭТе© T safeyAin S after ст & ст-(“Т”, z)eF( S)
=> ЭРеРи© P safe¡by S after ст & ст-(“Р”, z)eF{S),
3) Q safe i by S after ст => Q safeyAin S after cr&ElveQ ct(“Q”, v)e F( S).
На основе отношений безопасности кнопок в реализации и спецификации определяются безопасные действия, безопасные Р/@-истории Safe¡In (I) и Safe¡By (S), гипотеза о безопасности и безопасная конформность аналогично тому, как это делалось для трасс в случае машины без приоритетов. Отличия сводятся к следующему:
В определении безопасности Р/@-истории и в гипотезе о безопасности следует говорить не о трассе (у), а об истории (у), то есть о разрушении, выполнимом без нажатия кнопок (0-выполнимом).
I safefor S =def (<“0”,y)gF(S) <“0”,y)gF(I) )
& Vct Е Safe ¡By (S) rSafejIn (I) V P ePu©
(P safe i by S after ст => P safe¡in I after ст).
В определении множества наблюдений, которые можно получить над моделью Т при нажатии кнопки Р после трассы ст, вместо продолжения трассы наблюдением нужно говорить о продолжении Р/@-истории кнопкой и наблюдением:
obs{a, Р,Т) =def {и | ст-(“Р”, u)eF {Т) & (ueP v и=Р & РеР)}.
I saco S =def I safe for S
& h (ESafe ¡By (S) r,Safe i in (I) VP safe ¡by S after ст obs (ст, P, I) cobs (ст, P, S).
3.7. Безопасность и конформность с переключением кнопок
Если допускается переключение кнопок, мы можем обходить запрет на возникновение ненаблюдаемого отказа после нажатия ©-кнопки Q, а также дивергенцию, просто переключая её на другую кнопку Р. Соответственно, модифицируются отношения безопасности: удаляются условия в
определениях safe¡in и safe¡by, подчёркнутые волнистой линией, и остаются условия, связанные только с разрушением.
Определение отношения безопасности в реализации с переключением кнопок: Р safe2in I after ст =def Р safein I after ст.
Требования к отношению безопасности в спецификации с переключением кнопок: VReP VzeL VQe©
1) R safe2by S after ст R safein S after ст,
2) ЭТе© T safeyin S after ст & ст-(“Т”, z)eF {S)
=> ЭРеРи© P safe2by S after ст & ст-(“Р”, z)eF {S),
3) Q safe2by S after ст => Q safein S after ст.
Однако возникает вопрос: сколько раз оператор может переключать кнопки? Здесь нужно учитывать, что целью нажатия кнопок является получение, в конечном счёте, некоторого наблюдения. Поскольку мы рассматриваем только конечные (по времени выполнения) тесты, цепочка переключений кнопок должна быть конечной, то есть заканчиваться нажатием кнопки, после которой оператор ожидает гарантированного наблюдения, что даёт ему возможность, в частности, закончить сеанс тестирования. Это означает, что все кнопки в цепочке, кроме последней, безопасны после непосредственно предшествующего им префикса истории по отношению safe2in/by, а последняя кнопка — по отношению safe ¡in/by:
Р safein I after ст =def 3P0=P, Plr..., PnePu©
& Vi=0..n-1 Pi safe2in I after ct-(“P0”, “Pi”, ..., “Pi-i”)
& Pn safein I after ct-(“P0”, “Pi”, ..., “Pn-i”),
P safe by S after ст =def 3Po=P,Pi,...,PnePu0 & Vi=0..n-1 Pi safe2by S after ct-(“P0”, “Pi”, ..., “Pi-i”)
& Pn safety S after ct-<“P0”, “Pi”,..., “Pn_i”).
Таким образом, отношение безопасности с индексом ‘У’ определяет продолжение истории кнопкой, не вызывающей разрушение, а отношение безопасности с индексом дополнительно запрещает ненаблюдаемый отказ и дивергенцию. Понятно, что 2-безопасная кнопка также и 1-безопасна, но обратное, вообще говоря, не верно. Для полной безопасности кнопки после истории требуется, чтобы она была 1-безопасна, и после неё можно было поместить конечную цепочку 1-безопасных кнопок, а затем 2-безопасную кнопку, гарантирующую наблюдение.
На основе отношений безопасности кнопок в реализации и спецификации определяются безопасные действия, безопасные истории, гипотеза о безопасности и безопасная конформность аналогично тому, как это делалось для случая без переключения кнопок. Отличия сводятся к следующему:
1) В гипотезе о безопасности из i-безопасности кнопки в спецификации должна следовать тоже i-безопасность кнопки в реализации, где i= 1,2:
I safefor S =def (<“0”,y)gF(S) =s> <“0”,y)gF(I) )
& eSafe Ну (S) rSafeln (I) VPePu©
(P safe¡ by S after a => P safe¡ in I after a).
2) В определении конформности вложенность множеств наблюдений должна требоваться только после 1-безопасных историй, то есть историй, заканчивающихся на 1-безопасную кнопку:
I saco S =def I safefor S
& VneSafeliy (S) rSafeln (I) VP safe¡by S after a obs (a, P, I) cobs (ct, P, S).
3.8. Параллельная композиция и генерация тестов
Рассмотрим композицию двух LTS с приоритетами I и Т в алфавитах, соответственно, А и В. Возьмём любое композиционное состояние it. При композиции множество разрешённых внешних действий для LTS I в состоянии i — это множество противоположных внешних действий, по которым есть переходы из состояния t другой LTS Т, и наоборот. Поэтому, прежде всего, нам нужно пересчитать предикаты переходов из этих состояний. В силу коммутативности оператора композиции (с точностью до изоморфизма, то есть именования состояний it или ti), нам достаточно рассмотреть только пересчёт предикатов одной LTS, для определённости, LTS I. Для перехода i—z,п —>± ' мы должны в предикат п . понимаемый как булевская функция от булевских переменных-действий, подставить константное значение каждой переменной, соответствующей синхронному действию zeAnB. Если есть переход t—z, п —>t . то подставляется значение true, иначе — false. Получается новый предикат nit. Заметим, что вычисление нового предиката на переходе из состояния i зависит от состояния t, с которым оно компонуется, то есть для разных состояний t будут разные предикаты nit.
Новый предикат nit может быть не константным, поскольку в нём могут остаться переменные, соответствующие асинхронным внешним действиям из А\В. Кроме того, теперь этот предикат следует понимать как предикат в композиционном алфавите A=íB= (А\В) и (В\А), хотя реально он не зависит от переменных, соответствующих действиям из В\А.
Асинхронный переход соответствует одному переходу в одном из LTS-операндов. Он может выполняться, если может выполняться наследуемый переход. Следовательно, предикат асинхронного композиционного перехода совпадает с предикатом наследуемого перехода после пересчёта, то есть не с исходным предикатом 7г±, а с предикатом nit. Синхронный переход — это одновременное выполнение переходов в каяедом LTS-операнде. Он может выполняться, если могут выполняться оба перехода-операнда. Следовательно,
предикат синхронного композиционного перехода равен конъюнкции пересчитанных переходов-операндов 7г . В целом композиционные переходы порождаются следующими правилами вывода:
(1*) Z6{X,y}uA\B & i---Z,7li—>i' Dit—z, 7ilt—>i ' t,
(2*) ze{x,y}uB\A & t—z,7it—>t' Dit—z,7iti—>it ',
(3*) zeAr^B & i----Z,7li—>i' & t---Z, 7lt—>t ' Dit-T,7lit&7rti—' t ' .
Как и в случае машины без приоритетов тестирование понимается как композиция LTS-реализации I в алфавите А и LTS-теста Т в противоположном алфавите В=А. Мы также будем предполагать, что в тесте нет разрушения. Переходы по внешним действиям в тесте не имеют предикатов, точнее их предикаты тождественно истинны. Поэтому в композиционной LTS все переходы (а это уже только х- и у-переходы) — это пересчитанные предикаты переходов реализации. Поскольку композиционный алфавит пуст, эти предикаты константны (true или false).
Для обнаружения отказов в тесте (но не в реализации!) также используются 9-переходы с тождественно истинными переходами. Если нет переключения кнопок, такой переход срабатывает тогда и только тогда, когда никакие другие переходы не могут выполняться:
(4*) t—9—>t ' & Deadlock ( i,t) □ it—x—>it',
где Deadlock (i,t) = i—x,7rlt| & i—y,n^ \ & t—x I & (VzeAnB i—z,7ilt| v t—zj ).
Если допускается переключение кнопок, то в тесте оно отображается в виде х-перехода “Р”—x—»“Q” из состояния, соответствующего одной кнопке Р, в состояние, соответствующее другой кнопке Q. 9-переход определяется в состоянии “Р”, если кнопка Р — это P-кнопка. Нужно, чтобы 9-переход мог срабатывать независимо от х-перехода переключения кнопок “Р”—x—»“Q”: удаляется условие t—х |, подчёркнутое волнистой линией.
Мы будем рассматривать только безопасные реализации и безопасные тесты. Под безопасным тестом здесь понимается тест, при взаимодействии которого с любой безопасной реализацией не возникают разрушение, дивергенция, выполнимая после нажатия кнопки, а также тупики. Такие тесты строятся на основе безопасных историй спецификации. Тестовая история — это либо безопасная история спецификации, либо безопасная история спецификации, заканчивающаяся кнопкой, которая продолжена наблюдением (действием или P-отказом), отсутствующим после этой истории в спецификации. Также мы будем рассматривать только такие тесты, которые заканчиваются через конечное время; мы будем называть их конечными тестами. Для безопасного LTS-теста это означает отсутствие в нём бесконечных маршрутов.
ст=(“А”,А,“В”,Ь,“С”,с), где A, BeP, Ce@.
Внешнее действие имеет индекс «;;орошо», если оно есть в спецификации после префикса истории; иначе — индекс «пло::о».
Пунктиром показаны взаимоисключающие 9-переходы, ведущие из одного состояния. Индексы ^::орошо^ и « » означают
наличие или отсутствие продолжения префикса истории соответствующим Р-отказом.
Маленькими серыми кружками показаны пустые состояния._________________
Рис. 5. Примитивный тест для безопасной R/0-истории а.
В композиции теста с реализацией все предикаты константны, мы можем удалить все переходы с ложными предикатами. Если реализация безопасна, а тест конечен и безопасен, то оставшиеся у-переходы недостижимы. Как и для машины без приоритетов выполнению теста соответствует прохождение х-маршрута, начинающегося в начальном состоянии композиции и заканчивающегося в композиционном состоянии it, где t терминальное состояние теста, которому назначен вердикт pass или fail. Заметим, что в композиции могут быть бесконечные маршруты, но они не могут проходиться при тестировании. Действительно, поскольку тест конечен, в таком маршруте, начиная с некоторого места, состояние теста не меняется: дальше идут только асинхронные х-переходы реализации. В процессе тестирования оператор машины всегда за конечное время дожидается наблюдения, нажимает или переключает кнопку, что означает смену состояния теста и, тем самым, прекращение выполнения бесконечной цепочки х-переходов реализации. Здесь мы опираемся на то, что за конечное время может выполняться только конечная цепочка переходов. Оператор может также выключить машину (окончание тестирования), что происходит через конечное время после наблюдения.
Тест должен взаимодействовать с реализацией, согласно той Р/©-семантики, в которой рассматривалась спецификация, по которой тест сгенерирован.
fail'
^хороший € _А_
• pass
fail* - - ■
-*• pass pass
fail"
СПЛОХОЙ £ С
С хороший £ С
' pass
pass
Поэтому в каждом состоянии теста множество действий, по которым определены переходы из состояния, должно соответствовать Р- или ©-кнопке, причём для Р-кнопки дополнительно должен быть определён 9-переход. Мы приняли допущение о том, что сразу после включения машины до нажатия первой кнопки, после любого наблюдения, а также при переключении кнопок в реализации могут выполняться 0-выполнимые х- и у-переходы. Это допущение является частью семантики взаимодействия, которую должен соблюдать тест. Поэтому нужно ввести в тест дополнительные пустые состояния, соответствующие ситуации, когда нет нажатых кнопок. Эти состояния теста должны позволять реализации совершать 0-выполнимые х-переходы. При отжатых кнопках множество разрешённых действий пусто, поэтому в пустом состоянии могут быть определены только х-переходы. Эти х-переходы, в конечном счёте, должны приводить к непустым состояниям, соответствующим той или иной кнопке (пустая Р-кнопка соответствует состоянию, в котором определён 9-переход, а пустую ©-кнопку мы запретили). Такой пустой кнопкой должно быть начальное состояние и постсостояние каждого перехода по наблюдению, если это не терминальное состояние.
Примитивный тест строится аналогично тому, как это делается для машины без приоритетов. Но есть три отличия. 1) Без приоритетов мы строили тест по безопасной Р-трассе, превращая её в одну из Р/©-историй, а теперь сразу начинаем с некоторой безопасной Р/©-истории. 2) Если в истории есть переключение с кнопки Р на кнопку 0., то в тесте проводится х-переход “Р”—х—»“0”. 3) Добавляются пустые состояния. По-прежнему, набор всех примитивных тестов полон, а любой строгий тест можно заменить на объединение примитивных тестов, которое обнаруживает те же самые ошибки.
3.9. Примеры задания приоритетов
Покажем, как задаются приоритеты с помощью предикатов на переходах ЬТ8-модели для примеров, приведённых во введении.
Выход из дивергенции. Переход по внешнему действию имеет тождественно истинный предикат, а х-переход имеет предикат п, истинный только на пустом подмножестве алфавита внешних действий: п (и) = (и=0).
Выход из осцилляции (приоритет приёма над выдачей). Переход по стимулу имеет тождественно истинный предикат, а переход по реакции имеет предикат л, истинный на любом подмножестве действий, не содержащем стимулов: 71 (и) = (V ? х ? х £ и). Обычно также подразумевается, что внутренняя активность менее приоритетна, чем приём стимула, то есть х-переход имеет такой же предикат, как переход по реакции.
Приоритет выдачи над приёмом в неограниченных очередях. Переход по реакции имеет тождественно истинный предикат, а переход по стимулу имеет 48
предикат л, истинный на любом подмножестве действий, не содержащем реакцию: 7t (U) = (V ! у !ygU). Обычно также подразумевается, что
внутренняя активность менее приоритетна, чем выдача реакции, то есть х-переход имеет такой же предикат, как переход по стимулу.
Прерывание цепочки действий. Переход по команде «отменить» (cancel) имеет тождественно истинный предикат, а все остальные переходы имеют предикат 7г, истинный на любом подмножестве действий, не содержащем “cancel”: 7г (и) = (cancelgu).
Приоритетная обработка входных воздействий. Множество стимулов разбивается на непересекающиеся подмножества X , X ,... так, что стимулы из подмножества с большим индексом имеют больший приоритет. Предикат 7ii на переходе по стимулу из Xi истинен на любом подмножестве действий, не содержащем стимулы из подмножества с большим номером: 7ii(U) = (Vj>i UnXj=0). Возможна также дифференциация переходов из некоторого состояния по одному и тому же стимулу в зависимости от наличия или отсутствия менее приоритетных стимулов. Например, один переход по стимулу из Xi выполняется, если окружение предлагает менее приоритетные стимулы 7Гц (U) =7ii (U) & (3 j<i UnXj^0), в предположении, что это предложение сохранится, и эти стимулы можно будет обработать потом, а другой переход выполняется, если менее приоритетных стимулов нет 7Г12 (U) =П± (U) & (Vj<i UnXj=0). Если в состоянии нет переходов по стимулам, то такая дифференциация возможна и между переходами по реакциям и/или х-переходам.
Возможна реализация и более экзотических приоритетов. Например, циклический приоритет движения по сторонам света: идём на север, если нельзя идти на восток; идём на восток, если нельзя идти на юг; идём на юг, если нельзя идти на запад; идём на запад, если нельзя идти на север. Если разрешены все четыре направления, выбирается любое. Кроме этого случая, равноприоритетными оказываются только противоположные направления при отсутствии остальных. Предикат перехода на север выглядит так Лсевер(и) = (востокги v и={север,восток,юг,запад}). Аналогично устроены предикаты переходов на восток, юг и запад.
4. Заключение
Можно рассматривать семантики, в которых при включении машины, после наблюдения и при переключении кнопок может не допускаться выполнение реализацией х- и у-переходов, даже если они 0-выполнимы. Можно считать, что сразу после включения машины и сразу после наблюдения реализация стоит, и может выполнять какие-то действия только после нажатия кнопки. Также переключение кнопок не интерпретируется как отжатие первой кнопки (с разрешением 0-выполнимых х- и у-действий), а потом нажатие второй
кнопки. Иными словами, после включения машины, после наблюдения и между двумя кнопками при переключении кнопок нет никакого «пустого» промежутка. Такая семантика, очевидно, предполагает более сильные тестовые возможности, чем слабая семантика, рассматриваемая в данной статье. Эти семантики имеют разные требования по безопасности и конформности.
Любое поведение, которое можно наблюдать при сильной семантике, можно наблюдать и при слабой семантике. Достаточно подобрать подходящие погодные условия, когда оператор успевает нажать или переключить кнопку достаточно быстро. Верно и обратное: поведение при слабой семантике наблюдается при сильной семантике, если добавить пустую кнопку и явно нажимать её. Однако условия безопасности для этих семантик разные. При слабой семантике мы всегда должны рассчитывать на возможность выполнения х- и у-действий (при наличии приоритетов, они должны быть 0-выполнимы) после наблюдения по кнопке Р, а такие действия могут давать дивергенцию или разрушение; тем самым, кнопка Р будет опасной. При сильной семантике мы можем просто не нажимать в этой ситуации пустую кнопку после такого наблюдения, поскольку она опасна, а кнопка Р будет безопасной. Отсюда же вытекают и различия в конформности: реализация может быть опасной при слабой семантике и, следовательно, не конформной, но безопасной и конформной при сильной семантике. При тех же условиях безопасности (например, когда в спецификации нет дивергенции, разрушения и ненаблюдаемых отказов) и при наличии приоритетов сильная семантика предъявляет более жёсткие условия конформности. Это объясняется тем, что мы получаем возможность различать реализации, в которых некое действие Ь, разрешаемой кнопкой В, выполняется сразу после действия а или через промежуточную 0-выполнимую, но не В-выполнимую х-активность.
Кроме генерации тестов, важнейшей проблемой теории конформности является проблема монотонности — сохранения конформности при композиции. В общем случае композиция реализаций, конформных своим спецификациям, может быть не конформна композиции этих спецификаций. Частным, но важным, случаем этой проблемы является проблема асинхронного тестирования, когда имеется два компонента: реализация и известная среда передачи. Здесь также композиция конформной реализации со средой может быть не конформна композиции спецификации с этой средой.
Для машин без приоритетов эта проблема решается с помощью монотонного преобразования спецификаций: композиция конформных реализаций
оказывается конформной композиции преобразованных спецификаций. Для асинхронного тестирования: композиция конформной реализации со средой конформна композиции преобразованной спецификации с этой средой. Монотонное преобразование выполняется для Р/©-семантик, в которых все отказы наблюдаемы, то есть ©=0. В общем случае Р/©-семантики сначала выполняется пополнение спецификации. Пополненная спецификация 50
эквивалентна (имеет тот же класс безопасных и тот же класс конформных реализаций) исходной спецификации в Р/0-семантике, а кроме того, эквивалентна сама себе в Pu©/0-семантике. Пополнение решает также проблему рефлексивности («самоприменимости») спецификации, которая в Р/© -семантике может быть не конформна сама себе. Тем самым, совокупность преобразования пополнения и монотонного преобразования решает общую проблему монотонности и рефлексивности для любой Р/©-семантики [13,15,16].
Для машин с приоритетами проблемы монотонности и рефлексивности ещё не решены.
Литература
[1] И. Б. Бурдонов, А. С. Косачев, В. В. Кулямин. Использование конечных автоматов для тестирования программ. Программирование, 26(2):61-73, 2000.
[2] И. Б. Бурдонов, А. С. Косачев, В. В. Кулямин. Асинхронные автоматы: классификация и тестирование. Труды ИСП РАН, 4:7-84, 2003.
[3] И. Б. Бурдонов, А. С. Косачев, В. В. Кулямин. Неизбыточные алгоритмы обхода ориентированных графов. Детерминированный случай. Программирование,
29(5):59-69, 2003.
[4] В. В. Кулямин, А. К. Петренко, А. С. Косачев, И. Б. Бурдонов. Подход UniTesK к разработке тестов. Программирование, 29(6):25^3, 2003.
[5] V. V. Kuliamin, А. К. Petrenko, N. V. Pakoulin, A. S. Kossatchev, I. В. Bourdonov Intégration of Functional and Timed Testing of Real-Time and Concurrent Systems. Proceedings of PSI 2003, LNCS 2890:450^61, Springer-Verlag, 2003.
[6] И. Б. Бурдонов, A. С. Косачев, В. В. Кулямин. Неизбыточные алгоритмы обхода ориентированных графов. Недетерминированный случай. Программирование,
30(1 ):2—17, 2004.
[7] И. Б. Бурдонов. Обход неизвестного ориентированного графа конечным роботом. «Программирование», 2004, No. 4.
[8] И. Б. Бурдонов. Проблема отката по дереву при обходе неизвестного ориентированного графа конечным роботом. «Программирование», 2004, No. 6.
[9] И. Б. Бурдонов. Исследование одно/двунаправленных распределённых сетей конечным роботом. Труды Всероссийской научной конференции "Научный сервис в сети ИНТЕРНЕТ". 2004.
[10] И. Б. Бурдонов, А. С. Косачев. Тестирование компонентов распределенной системы. Труды Всероссийской научной конференции «Научный сервис в сети ИНТЕРНЕТ», Изд-во МГУ, 2005.
[11] И. Б. Бурдонов, А. С. Косачев. Верификация композиции распределенной системы. Труды Всероссийской научной конференции «Научный сервис в сети ИНТЕРНЕТ», Изд-во МГУ, 2005.
[12] I. Bourdonov, A. Kossatchev, V. Kuliamin. Formai Conformance Testing of Systems with Refused Inputs and Forbidden Actions. Proceedings of МВТ 2006, Vienna,
Austria, March 2006.
[13] И. Б. Бурдонов, A. С. Косачев, В. В. Кулямин. Формализация тестового эксперимента. Программирование, 33(5):3-32, 2007.
[14] И. Б. Бурдонов, А. С. Косачев, В. В. Кулямин. Безопасность, верификация и теория конформности. Материалы Второй международной научной конференции по проблемам безопасности и противодействия терроризму, Москва, МНЦМО, 2007.
[15] И. Б. Бурдонов, А. С. Косачев, В. В. Кулямин. Теория соответствия для систем с блокировками и разрушением. «Наука», 2008.
[16] И. Б. Бурдонов. Теория конформности для функционального тестирования программных систем на основе формальных моделей. Диссертация на соискание учёной степени д.ф.-м.н., Москва, 2007.
http://www.ispras.ru/4ledVerst/RedVerst/Publications/TR-01-2007.pdf.
[17] М. П. Василевский. О распознавании неисправностей автомата. Кибернетика, 9(4):93-108, 1973.
[18] V. Aho, А. T. Dahbura, D. Lee, М. Ü. Uyar. An Optimization Technique for Protocol Conformance Test Generation Based on UIO Sequences and Rural Chinese Postman Tours. IEEE Transactions on Communications, 39(11 ): 1604—1615, 1991.
[19] A. Blass, Y. Gurevich, L. Nachmanson, M. Veanes. Play to Test Microsoft Research. Technical Report MSR-TR-2005-04, January 2005. 5-th International Workshop on Formal Approaches to Testing of Software (FATES 2005). Edinburgh, July 2005.
[20] J. Edmonds, E. L. Johnson. Matching. Euler Tours, and the Chinese Postman. Math. Programming 5:88-124, 1973.
[21] S. Fujiwara, G. v. Bochmann. Testing Nondeterministic Finite State Machine with Fault Coverage. In J. Kroon, R. J. Heijink, and E. Brinksma, eds. IFIP Transactions, Proceedings of IFIP TC6 Fourth International Workshop on Protocol Test Systems,
1991, North-Holland, pp. 267-280, 1992.
[22] R. J. van Glabbeek. The linear time-branching time spectrum. In J. С. M. Baeten and J. W. Klop, eds. CONCUR’90, LNCS 458:278-297, Springer-Verlag, 1990.
[23] R. J. van Glabbeek. The linear time — branching time spectrum II; the semantics of sequential processes with silent moves. In E. Best, ed. Proceedings CONCUR’93, Hildesheim, Germany, August 1993, LNCS 715:66-81, Springer-Verlag, 1993.
[24] J. B. Goodenough, S. L. Gerhart. Toward a theory of test data selection. IEEE Trans. Software Eng., 1(2): 156-173, June 1975.
[25] M. Grochtmann, K. Grimm. Classification trees for partition testing. Software Testing, Verification and Reliability, 3:63-82, 1993.
[26] L. Heerink, J. Tretmans. Refusal Testing for Classes of Transition Systems with Inputs and Outputs. In T. Mizuno, N. Shiratori, T. Higashino, A. Togashi, eds. Formal Description Techniques and Protocol Specification, Testing and Verification. Chapman
& Hill, 1997.
[27] L. Heerink. Ins and Outs in Refusal Testing. PhD thesis, University of Twente, Enschede, The Netherlands, 1998.
[28] D. Lee, M. Yannakakis. Testing Finite State Machines: State Identification and Verification. IEEE Trans, on Computers, 43(3):306-320, March 1994.
[29] D. Lee, M. Yannakakis. Principles and Methods of Testing Finite State Machines — A Survey. Proceedings of the IEEE 84(8): 1090-1123, 1996.
[30] B. Legeard, F. Peureux, M. Utting. Automated boundary testing from Z and B. In Proc. of the Int. Conf. on Formal Methods Europe, FME'02, Copenhaguen, Denmark,
July 2002, LNCS 2391:21^10, Springer, 2002.
[31] G. Lestiennes , M.-C. Gaudel. Test de systèmes reactifs non receptifs. Journal Europeen des Systernes Automatises, Modélisation des Systèmes Reactifs, pp. 255-270. Hermes, 2005.
[32] R. Milner. A Calculus of Communicating Processes. LNCS 92, Springer-Verlag, 1980.
[33] R. Milner. Modal characterization of observable machine behaviour. In G. Astesiano,
C. Bohm, eds. Proceedings CAAP’81, LNCS 112:25-34, Springer, 1981.
[34] R. Milner. Communication and Concurrency. Prentice-Hall, 1989.
[35] A. Petrenko, N. Yevtushenko, G. v. Bochmann. Testing deterministic implementations from nondeterministic FSM specifications. Selected proceedings of the IFIP TC6 9-th international workshop on Testing of communicating systems, September 1996.
[36] A. Petrenko, N. Yevtushenko, J. L. Huo. Testing Transition Systems with Input and Output Testers. Proc. IFIP TC6/WG6.1 15-th Int. Conf. Testing of Communicating Systems, TestCom’2003, pp. 129-145. Sophia Antipolis, France, May 2003.
[37] H. Zhu, P. A. V. Hall, J. H. R. May. Software Unit Test Coverage and Adequacy. ACM Computing Surveys, 29(4):366^127, Dec. 1997.