diff --git "a/docs/\320\224\320\270\320\260\320\263\320\275\320\276\321\201\321\202\320\270\320\272\320\260\320\236\321\210\320\270\320\261\320\276\320\272.md" "b/docs/\320\224\320\270\320\260\320\263\320\275\320\276\321\201\321\202\320\270\320\272\320\260\320\236\321\210\320\270\320\261\320\276\320\272.md" index 9013fa3..9e95de4 100644 --- "a/docs/\320\224\320\270\320\260\320\263\320\275\320\276\321\201\321\202\320\270\320\272\320\260\320\236\321\210\320\270\320\261\320\276\320\272.md" +++ "b/docs/\320\224\320\270\320\260\320\263\320\275\320\276\321\201\321\202\320\270\320\272\320\260\320\236\321\210\320\270\320\261\320\276\320\272.md" @@ -138,7 +138,7 @@ - `КраткоеПредставление` возвращает компактную строку с текущим кадром и эффективной ошибкой. - `ПользовательскоеПредставление` дополнительно выводит подсказку и URL текущего кадра. -- `ДиагностическоеПредставление` формирует полный отчёт по цепочке со стеком и данными. +- `ДиагностическоеПредставление` формирует отчёт по цепочке со стеком и данными. Диагностическое представление предназначено для логов и отладки. Оно может раскрывать пользовательские данные, места возникновения и стек вызовов; не передавайте в данные ошибки diff --git "a/docs/\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\320\265\320\236\321\210\320\270\320\261\320\276\320\272.md" "b/docs/\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\320\265\320\236\321\210\320\270\320\261\320\276\320\272.md" index 2919111..b1101d8 100644 --- "a/docs/\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\320\265\320\236\321\210\320\270\320\261\320\276\320\272.md" +++ "b/docs/\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\320\265\320\236\321\210\320\270\320\261\320\276\320\272.md" @@ -42,7 +42,7 @@ URL: ## Диагностическое представление -`ДиагностическоеПредставление()` возвращает полный технический отчёт для логов и отладки. +`ДиагностическоеПредставление()` возвращает технический отчёт для логов и отладки. Внешний кадр выводится первым, все промежуточные причины объединяются в блок `Причина`, раскрываются `Данные` и добавляется общий стек вызовов первого физического кадра: diff --git "a/docs/\320\240\320\260\320\267\320\261\320\276\321\200\320\236\321\210\320\270\320\261\320\272\320\270.md" "b/docs/\320\240\320\260\320\267\320\261\320\276\321\200\320\236\321\210\320\270\320\261\320\272\320\270.md" index a139f3b..ab264f9 100644 --- "a/docs/\320\240\320\260\320\267\320\261\320\276\321\200\320\236\321\210\320\270\320\261\320\272\320\270.md" +++ "b/docs/\320\240\320\260\320\267\320\261\320\276\321\200\320\236\321\210\320\270\320\261\320\272\320\270.md" @@ -222,7 +222,7 @@ .ДиагностическоеПредставление() ``` -Возвращает полный диагностический отчёт с данными, всей цепочкой причин и стеком вызовов. +Возвращает диагностический отчёт с данными, цепочкой причин и стеком вызовов. #### Возвращаемое значение diff --git "a/src/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\205\320\276\320\264\321\207\320\270\320\272\320\246\320\265\320\277\320\276\321\207\320\272\320\270\320\236\321\210\320\270\320\261\320\272\320\270.os" "b/src/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\205\320\276\320\264\321\207\320\270\320\272\320\246\320\265\320\277\320\276\321\207\320\272\320\270\320\236\321\210\320\270\320\261\320\272\320\270.os" index 9a3bc35..a2c8e96 100644 --- "a/src/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\205\320\276\320\264\321\207\320\270\320\272\320\246\320\265\320\277\320\276\321\207\320\272\320\270\320\236\321\210\320\270\320\261\320\272\320\270.os" +++ "b/src/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\236\320\261\321\205\320\276\320\264\321\207\320\270\320\272\320\246\320\265\320\277\320\276\321\207\320\272\320\270\320\236\321\210\320\270\320\261\320\272\320\270.os" @@ -132,6 +132,48 @@ КонецФункции +// Проверяет, является ли кадр внешней обёрткой повторного выброса. +// Такая обёртка не содержит собственных метаданных и дословно повторяет описание причины. +// +// Параметры: +// Ошибка - ИнформацияОбОшибке - Проверяемый кадр. +// +// Возвращаемое значение: +// Булево - Истина, если кадр не добавляет нового описания к непосредственной причине. +Функция ЭтоПовторныйВыброс(Ошибка) Экспорт + + Причина = Неопределено; + Возврат ПопытатьсяПрочитатьПричинуПовторногоВыброса(Ошибка, Причина); + +КонецФункции + +// Возвращает первый кадр, не дублирующий описание непосредственной причины. +// +// Параметры: +// Ошибка - ИнформацияОбОшибке - Внешний кадр просматриваемой цепочки. +// КоличествоПросмотренныхКадров - Число - Выходной параметр количества кадров в общем бюджете обхода. +// +// Возвращаемое значение: +// ИнформацияОбОшибке - Исходный кадр или причина после пропуска повторных выбросов. +Функция ПропуститьПовторныеВыбросы(Ошибка, КоличествоПросмотренныхКадров = 1) Экспорт + + ТекущийКадр = Ошибка; + КоличествоПросмотренныхКадров = 1; + + Пока КоличествоПросмотренныхКадров < МаксимальноеКоличествоКадров() Цикл + Причина = Неопределено; + Если Не ПопытатьсяПрочитатьПричинуПовторногоВыброса(ТекущийКадр, Причина) Тогда + Возврат ТекущийКадр; + КонецЕсли; + + ТекущийКадр = Причина; + КоличествоПросмотренныхКадров = КоличествоПросмотренныхКадров + 1; + КонецЦикла; + + Возврат ТекущийКадр; + +КонецФункции + // Возвращает первую распознанную ошибку при обходе от внешнего кадра к причине. // // Параметры: @@ -249,6 +291,19 @@ #Область СлужебныеПроцедурыИФункции +Функция ПопытатьсяПрочитатьПричинуПовторногоВыброса(Ошибка, Причина) + + Причина = Неопределено; + Если Ошибка.Параметры <> Неопределено + Или Не ПопытатьсяПрочитатьПричину(Ошибка, Причина) + Или Причина = Неопределено Тогда + Возврат Ложь; + КонецЕсли; + + Возврат Ошибка.Описание = Причина.Описание; + +КонецФункции + Функция НайтиПервыйКадр(Ошибка, УсловиеПоиска, ВидПоиска) ТекущийКадр = Ошибка; diff --git "a/src/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\244\320\276\321\200\320\274\320\260\321\202\320\270\321\200\320\276\320\262\321\211\320\270\320\272\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" "b/src/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\244\320\276\321\200\320\274\320\260\321\202\320\270\321\200\320\276\320\262\321\211\320\270\320\272\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" index 7647133..b3e3484 100644 --- "a/src/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\244\320\276\321\200\320\274\320\260\321\202\320\270\321\200\320\276\320\262\321\211\320\270\320\272\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" +++ "b/src/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\244\320\276\321\200\320\274\320\260\321\202\320\270\321\200\320\276\320\262\321\211\320\270\320\272\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" @@ -139,7 +139,7 @@ КонецФункции -// Формирует полный диагностический отчёт по просмотренным физическим кадрам. +// Формирует диагностический отчёт по просмотренным физическим кадрам без дублирующих транспортных обёрток. // // Параметры: // Снимки - Массив из СнимокКадраОшибки - Снимки от внешнего кадра к корневому. @@ -338,8 +338,17 @@ Новый Массив ); Контексты = Новый Массив; + Обходчик = СервисыБиблиотекиОшибок.ОбходчикЦепочкиОшибки(); + + Для НомерСнимка = 0 По Снимки.ВГраница() Цикл + Снимок = Снимки[НомерСнимка]; + Если Снимок.Вид() = ВидыКадровОшибок.ВнешняяОшибка() + И НомерСнимка < Снимки.ВГраница() + И Обходчик.ЭтоПовторныйВыброс(Снимок.ИсходнаяОшибка()) + И Снимок.ИсходнаяОшибка().Причина = Снимки[НомерСнимка + 1].ИсходнаяОшибка() Тогда + Продолжить; + КонецЕсли; - Для Каждого Снимок Из Снимки Цикл Подсказка = Снимок.Подсказка(); Если Не ПустаяСтрока(Подсказка) Тогда Результат.Подсказки.Добавить(Подсказка); diff --git "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\240\320\260\320\267\320\261\320\276\321\200\320\236\321\210\320\270\320\261\320\272\320\270.os" "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\240\320\260\320\267\320\261\320\276\321\200\320\236\321\210\320\270\320\261\320\272\320\270.os" index 66275e2..85c0820 100644 --- "a/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\240\320\260\320\267\320\261\320\276\321\200\320\236\321\210\320\270\320\261\320\272\320\270.os" +++ "b/src/\320\232\320\273\320\260\321\201\321\201\321\213/\320\240\320\260\320\267\320\261\320\276\321\200\320\236\321\210\320\270\320\261\320\272\320\270.os" @@ -227,7 +227,7 @@ КонецФункции -// Возвращает полный диагностический отчёт. +// Возвращает диагностический отчёт. // // Возвращаемое значение: // Строка - Семантические группы ошибки, контекстов и причин со стеком и данными. @@ -304,28 +304,42 @@ Возврат; КонецЕсли; - _СнимокПредставления = Новый СнимокКадраОшибки(_ИсходнаяОшибка); + ОшибкаПредставления = _ИсходнаяОшибка; + КоличествоПросмотренныхКадров = 1; + _СнимокПредставления = Новый СнимокКадраОшибки(ОшибкаПредставления); + + Если _СнимокПредставления.Вид() = ВидыКадровОшибок.ВнешняяОшибка() Тогда + Обходчик = СервисыБиблиотекиОшибок.ОбходчикЦепочкиОшибки(); + ОшибкаПредставления = Обходчик.ПропуститьПовторныеВыбросы( + _ИсходнаяОшибка, + КоличествоПросмотренныхКадров + ); + Если ОшибкаПредставления <> _ИсходнаяОшибка Тогда + _СнимокПредставления = Новый СнимокКадраОшибки(ОшибкаПредставления); + КонецЕсли; + КонецЕсли; Если _СнимокПредставления.Вид() = ВидыКадровОшибок.Ошибка() Тогда _КодЭффективнойОшибки = _СнимокПредставления.КодОшибки(); _СообщениеЭффективнойОшибки = _СнимокПредставления.Сообщение(); Иначе ЗаполнитьЭффективнуюОшибку( - _ИсходнаяОшибка, + ОшибкаПредставления, _КодЭффективнойОшибки, - _СообщениеЭффективнойОшибки + _СообщениеЭффективнойОшибки, + КоличествоПросмотренныхКадров ); КонецЕсли; КонецПроцедуры -Процедура ЗаполнитьЭффективнуюОшибку(Ошибка, КодОшибки, Сообщение) +Процедура ЗаполнитьЭффективнуюОшибку(Ошибка, КодОшибки, Сообщение, КоличествоПросмотренныхКадров = 1) ТекущийКадр = Ошибка; Обходчик = СервисыБиблиотекиОшибок.ОбходчикЦепочкиОшибки(); Читатель = СервисыБиблиотекиОшибок.ЧитательКадраОшибки(); - Для НомерКадра = 2 По Обходчик.МаксимальноеКоличествоКадров() Цикл + Для НомерКадра = КоличествоПросмотренныхКадров + 1 По Обходчик.МаксимальноеКоличествоКадров() Цикл Причина = Неопределено; Если Не Обходчик.ПопытатьсяПрочитатьПричину(ТекущийКадр, Причина) Или Причина = Неопределено Тогда @@ -371,7 +385,8 @@ Процедура ПодготовитьСнимок(Кадр, Ошибки) - Если Кадр = _ИсходнаяОшибка И _СнимокПредставления <> Неопределено Тогда + Если _СнимокПредставления <> Неопределено + И _СнимокПредставления.ИсходнаяОшибка() = Кадр Тогда Снимок = _СнимокПредставления; Иначе Снимок = Новый СнимокКадраОшибки(Кадр); diff --git "a/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\224\320\270\320\260\320\263\320\275\320\276\321\201\321\202\320\270\320\272\320\260\320\236\321\210\320\270\320\261\320\276\320\272.os" "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\224\320\270\320\260\320\263\320\275\320\276\321\201\321\202\320\270\320\272\320\260\320\236\321\210\320\270\320\261\320\276\320\272.os" index b392afa..377f5d6 100644 --- "a/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\224\320\270\320\260\320\263\320\275\320\276\321\201\321\202\320\270\320\272\320\260\320\236\321\210\320\270\320\261\320\276\320\272.os" +++ "b/src/\320\234\320\276\320\264\321\203\320\273\320\270/\320\224\320\270\320\260\320\263\320\275\320\276\321\201\321\202\320\270\320\272\320\260\320\236\321\210\320\270\320\261\320\276\320\272.os" @@ -181,7 +181,7 @@ КонецФункции -// Возвращает полный диагностический отчёт со стеком и данными ошибки. +// Возвращает диагностический отчёт со стеком и данными. // // Параметры: // Ошибка - ИнформацияОбОшибке - Внешний кадр разбираемой цепочки. diff --git "a/tests/fixtures/\320\232\320\273\320\260\321\201\321\201\321\213/\320\242\320\265\321\201\321\202\320\276\320\262\321\213\320\271\320\241\320\275\320\270\320\274\320\276\320\272\320\232\320\260\320\264\321\200\320\260\320\236\321\210\320\270\320\261\320\272\320\270.os" "b/tests/fixtures/\320\232\320\273\320\260\321\201\321\201\321\213/\320\242\320\265\321\201\321\202\320\276\320\262\321\213\320\271\320\241\320\275\320\270\320\274\320\276\320\272\320\232\320\260\320\264\321\200\320\260\320\236\321\210\320\270\320\261\320\272\320\270.os" index 1cf42cc..c093ae9 100644 --- "a/tests/fixtures/\320\232\320\273\320\260\321\201\321\201\321\213/\320\242\320\265\321\201\321\202\320\276\320\262\321\213\320\271\320\241\320\275\320\270\320\274\320\276\320\272\320\232\320\260\320\264\321\200\320\260\320\236\321\210\320\270\320\261\320\272\320\270.os" +++ "b/tests/fixtures/\320\232\320\273\320\260\321\201\321\201\321\213/\320\242\320\265\321\201\321\202\320\276\320\262\321\213\320\271\320\241\320\275\320\270\320\274\320\276\320\272\320\232\320\260\320\264\321\200\320\260\320\236\321\210\320\270\320\261\320\272\320\270.os" @@ -4,6 +4,7 @@ Перем _Данные; Перем _Подсказка; Перем _URL; +Перем _ИсходнаяОшибка; Перем _МестоСоздания; Перем _СтекВызовов; @@ -21,6 +22,8 @@ _Данные = ЗначениеСвойства(Параметры, "Данные", Неопределено); _Подсказка = ЗначениеСвойства(Параметры, "Подсказка", ""); _URL = ЗначениеСвойства(Параметры, "URL", ""); + _ИсходнаяОшибка = Новый ИнформацияОбОшибке(_Сообщение, Новый Структура); + МестоСоздания = Новый Структура( "ИмяМодуля, НомерСтроки, ИсходнаяСтрока", ЗначениеСвойства(Параметры, "ИмяМодуля", ""), @@ -28,6 +31,7 @@ ЗначениеСвойства(Параметры, "ИсходнаяСтрока", "") ); _МестоСоздания = Новый ФиксированнаяСтруктура(МестоСоздания); + _СтекВызовов = Новый Массив; Для Каждого Элемент Из ЗначениеСвойства(Параметры, "Стек", Новый Массив) Цикл _СтекВызовов.Добавить(Элемент); @@ -39,6 +43,16 @@ #Область ПрограммныйИнтерфейс +// Возвращает исходный физический кадр. +// +// Возвращаемое значение: +// ИнформацияОбОшибке - Тестовый исходный кадр. +Функция ИсходнаяОшибка() Экспорт + + Возврат _ИсходнаяОшибка; + +КонецФункции + // Возвращает вид кадра. // // Возвращаемое значение: diff --git "a/tests/fixtures/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\276\320\274\320\276\321\211\320\275\320\270\320\272\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" "b/tests/fixtures/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\276\320\274\320\276\321\211\320\275\320\270\320\272\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" index deaa2b1..c883712 100644 --- "a/tests/fixtures/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\276\320\274\320\276\321\211\320\275\320\270\320\272\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" +++ "b/tests/fixtures/\320\234\320\276\320\264\321\203\320\273\320\270/\320\237\320\276\320\274\320\276\321\211\320\275\320\270\320\272\320\242\320\265\321\201\321\202\320\270\321\200\320\276\320\262\320\260\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" @@ -57,6 +57,24 @@ КонецФункции +// Дважды повторно выбрасывает ошибку из разных мест исходного кода. +// +// Параметры: +// Ошибка - ИнформацияОбОшибке - Повторно выбрасываемая ошибка. +// +// Возвращаемое значение: +// Структура: +// * Ошибка - ИнформацияОбОшибке - Результат второго повторного выброса; +// * ВнутренняяОшибка - ИнформацияОбОшибке - Результат первого повторного выброса. +Функция ДваждыПовторноВыброшеннаяОшибка(Ошибка) Экспорт + + ВнутренняяОшибка = ПовторныйВыбросНаПервомУровне(Ошибка); + Ошибка = ПовторныйВыбросНаВторомУровне(ВнутренняяОшибка); + + Возврат Новый Структура("Ошибка, ВнутренняяОшибка", Ошибка, ВнутренняяОшибка); + +КонецФункции + // Создаёт кадр с повреждённым конвертом без обязательного поля Данные. // // Параметры: @@ -184,6 +202,26 @@ #Область СлужебныеПроцедурыИФункции +Функция ПовторныйВыбросНаПервомУровне(Ошибка) + + Попытка + ВызватьИсключение Ошибка; + Исключение + Возврат ИнформацияОбОшибке(); + КонецПопытки; + +КонецФункции + +Функция ПовторныйВыбросНаВторомУровне(Ошибка) + + Попытка + ВызватьИсключение Ошибка; + Исключение + Возврат ИнформацияОбОшибке(); + КонецПопытки; + +КонецФункции + Функция ВнешняяОшибкаНаПервойСтроке() Попытка diff --git "a/tests/\320\242\320\265\321\201\321\202\321\213\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" "b/tests/\320\242\320\265\321\201\321\202\321\213\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" index 535191b..2eb3f71 100644 --- "a/tests/\320\242\320\265\321\201\321\202\321\213\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" +++ "b/tests/\320\242\320\265\321\201\321\202\321\213\320\237\321\200\320\265\320\264\321\201\321\202\320\260\320\262\320\273\320\265\320\275\320\270\321\217\320\236\321\210\320\270\320\261\320\276\320\272.os" @@ -4,6 +4,62 @@ #Область Тесты +&Тест +Процедура ТестДолжен_НеДублироватьПредставленияПослеДвухПовторныхВыбросов() Экспорт + + // Подготовка + Ошибка = ФабрикаОшибок.Создать("storage.read_failed", "Ошибка чтения"); + Цепочка = ПомощникТестированияОшибок.ДваждыПовторноВыброшеннаяОшибка(Ошибка); + Ошибка = Цепочка.Ошибка; + ВнутренняяОшибка = Цепочка.ВнутренняяОшибка; + + // Действие + Разбор = ДиагностикаОшибок.Разобрать(Ошибка); + ПользовательскоеПредставление = Разбор.ПользовательскоеПредставление(); + КраткоеПредставление = Разбор.КраткоеПредставление(); + ДиагностическоеПредставление = Разбор.ДиагностическоеПредставление(); + СтруктурированноеПредставление = Разбор.ВСтруктуру(); + + // Проверка + Ожидаем.Что(КраткоеПредставление).Равно("storage.read_failed: Ошибка чтения"); + Ожидаем.Что(ПользовательскоеПредставление).Равно("storage.read_failed: Ошибка чтения"); + Ожидаем.Что(Разбор.Снимки().Количество()).Равно(2); + Ожидаем.Что(Разбор.Снимки()[0].ИсходнаяОшибка()).Равно(Ошибка); + Ожидаем.Что(Разбор.Снимки()[1].ИсходнаяОшибка()).Равно(ВнутренняяОшибка); + Ожидаем.Что(СтруктурированноеПредставление.Цепочка.Количество()).Равно(2); + Ожидаем.Что(СтрЧислоВхождений( + ДиагностическоеПредставление, + "storage.read_failed: Ошибка чтения" + )).Равно(1); + Ожидаем.Что(ДиагностическоеПредставление).ЭтоНе().Содержит("Причина:"); + Ожидаем.Что(ДиагностическоеПредставление).Содержит("Стек вызовов:"); + Ожидаем.Что(ДиагностическоеПредставление).Содержит("ПовторныйВыбросНаВторомУровне"); + +КонецПроцедуры + +&Тест +Процедура ТестДолжен_СохранитьВнешнийКадрССовпадающимОписаниемИСобственнымиПараметрами() Экспорт + + // Подготовка + Причина = ФабрикаОшибок.Создать("storage.read_failed", "Ошибка чтения"); + Ошибка = ПомощникТестированияОшибок.ВнешняяОшибка(Причина.Описание, Причина); + + // Действие + КраткоеПредставление = ДиагностикаОшибок.КраткоеПредставление(Ошибка); + ДиагностическоеПредставление = ДиагностикаОшибок.ДиагностическоеПредставление(Ошибка); + + // Проверка + Ожидаем.Что(КраткоеПредставление).Равно( + "storage.read_failed: storage.read_failed: Ошибка чтения -> Ошибка чтения" + ); + Ожидаем.Что(СтрЧислоВхождений( + ДиагностическоеПредставление, + "storage.read_failed: Ошибка чтения" + )).Равно(2); + Ожидаем.Что(ДиагностическоеПредставление).Содержит("Причина:"); + +КонецПроцедуры + &Тест Процедура ТестДолжен_ВернутьКраткоеПредставлениеТекущегоКадра() Экспорт diff --git "a/tests/\320\242\320\265\321\201\321\202\321\213\320\241\320\275\320\270\320\274\320\272\320\260\320\232\320\260\320\264\321\200\320\260\320\236\321\210\320\270\320\261\320\272\320\270.os" "b/tests/\320\242\320\265\321\201\321\202\321\213\320\241\320\275\320\270\320\274\320\272\320\260\320\232\320\260\320\264\321\200\320\260\320\236\321\210\320\270\320\261\320\272\320\270.os" index 3e8b8ce..587b715 100644 --- "a/tests/\320\242\320\265\321\201\321\202\321\213\320\241\320\275\320\270\320\274\320\272\320\260\320\232\320\260\320\264\321\200\320\260\320\236\321\210\320\270\320\261\320\272\320\270.os" +++ "b/tests/\320\242\320\265\321\201\321\202\321\213\320\241\320\275\320\270\320\274\320\272\320\260\320\232\320\260\320\264\321\200\320\260\320\236\321\210\320\270\320\261\320\272\320\270.os" @@ -35,6 +35,69 @@ КонецПроцедуры +&Тест +Процедура ТестДолжен_РаспознатьТолькоПовторныйВыбросБезПараметров() Экспорт + + // Подготовка + Причина = ФабрикаОшибок.Создать("storage.read_failed", "Ошибка чтения"); + ПервыйВыброс = ПомощникТестированияОшибок.ПовторноВыброшеннаяОшибка(Причина); + ПовторныйВыброс = ПомощникТестированияОшибок.ПовторноВыброшеннаяОшибка(ПервыйВыброс); + ВнешнийКадр = ПомощникТестированияОшибок.ВнешняяОшибка(Причина.Описание, Причина); + Обходчик = СервисыБиблиотекиОшибок.ОбходчикЦепочкиОшибки(); + КоличествоПросмотренныхКадров = 0; + + // Действие + ЭтоПовторныйВыброс = Обходчик.ЭтоПовторныйВыброс(ПовторныйВыброс); + ЭтоВнешнийКадр = Обходчик.ЭтоПовторныйВыброс(ВнешнийКадр); + КадрПредставления = Обходчик.ПропуститьПовторныеВыбросы( + ПовторныйВыброс, + КоличествоПросмотренныхКадров + ); + + // Проверка + Ожидаем.Что(ПовторныйВыброс.Параметры).Равно(Неопределено); + Ожидаем.Что(ЭтоПовторныйВыброс).ЭтоИстина(); + Ожидаем.Что(ЭтоВнешнийКадр).ЭтоЛожь(); + Ожидаем.Что(КадрПредставления).Равно(ПервыйВыброс); + Ожидаем.Что(КоличествоПросмотренныхКадров).Равно(2); + +КонецПроцедуры + +&Тест +Процедура ТестДолжен_НеИскатьКадрПредставленияЗаГраницейПросмотра() Экспорт + + // Подготовка + СтруктурированнаяОшибка = ФабрикаОшибок.Создать("storage.read_failed", "Ошибка чтения"); + Ошибка = СтруктурированнаяОшибка; + Для НомерВыброса = 1 По 65 Цикл + Ошибка = ПомощникТестированияОшибок.ПовторноВыброшеннаяОшибка(Ошибка); + КонецЦикла; + Обходчик = СервисыБиблиотекиОшибок.ОбходчикЦепочкиОшибки(); + КоличествоПросмотренныхКадров = 0; + + // Действие + КадрПредставления = Обходчик.ПропуститьПовторныеВыбросы( + Ошибка, + КоличествоПросмотренныхКадров + ); + СнимокПредставления = Новый СнимокКадраОшибки(КадрПредставления); + Просмотр = Обходчик.Просмотреть(Ошибка); + ДиагностическоеПредставление = ДиагностикаОшибок.ДиагностическоеПредставление(Ошибка); + + // Проверка + Ожидаем.Что(Просмотр.Кадры.Количество()).Равно(64); + Ожидаем.Что(Просмотр.Усечена).ЭтоИстина(); + Ожидаем.Что(КоличествоПросмотренныхКадров).Равно(64); + Ожидаем.Что(КадрПредставления = СтруктурированнаяОшибка).ЭтоЛожь(); + Ожидаем.Что(СнимокПредставления.Вид()).Равно(ВидыКадровОшибок.ВнешняяОшибка()); + Ожидаем.Что(СтрЧислоВхождений( + ДиагностическоеПредставление, + "storage.read_failed: Ошибка чтения" + )).Равно(1); + Ожидаем.Что(ДиагностическоеПредставление).Содержит("Цепочка причин усечена"); + +КонецПроцедуры + &Тест Процедура ТестДолжен_СоздатьСнимокСобственногоКадра() Экспорт