From 1a17d5f3b9133e6a3311e22c2b030542f1048407 Mon Sep 17 00:00:00 2001 From: Igor Storozhuk Date: Mon, 15 Jun 2026 14:39:38 +0300 Subject: [PATCH 1/2] feat: dispatch plugins in priority order (descending) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Приоритет() was declared in the plugin interface but never used for ordering event handler dispatch. МенеджерПодписок now sorts subscribers by Приоритет() descending before calling each handler, making execution order deterministic and controllable by plugin authors. Co-Authored-By: Claude Sonnet 4.6 --- ...20\277\320\270\321\201\320\276\320\272.os" | 21 ++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git "a/src/core/\320\232\320\273\320\260\321\201\321\201\321\213/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\234\320\265\320\275\320\265\320\264\320\266\320\265\321\200\320\237\320\276\320\264\320\277\320\270\321\201\320\276\320\272.os" "b/src/core/\320\232\320\273\320\260\321\201\321\201\321\213/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\234\320\265\320\275\320\265\320\264\320\266\320\265\321\200\320\237\320\276\320\264\320\277\320\270\321\201\320\276\320\272.os" index a8cc96b5..39da4be6 100644 --- "a/src/core/\320\232\320\273\320\260\321\201\321\201\321\213/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\234\320\265\320\275\320\265\320\264\320\266\320\265\321\200\320\237\320\276\320\264\320\277\320\270\321\201\320\276\320\272.os" +++ "b/src/core/\320\232\320\273\320\260\321\201\321\201\321\213/internal/\320\232\320\273\320\260\321\201\321\201\321\213/\320\234\320\265\320\275\320\265\320\264\320\266\320\265\321\200\320\237\320\276\320\264\320\277\320\270\321\201\320\276\320\272.os" @@ -774,16 +774,31 @@ Процедура ВыполнитьПодпискуНаСобытие(Знач ИмяПроцедурыВыполнения, ПараметрыПроцедуры) - Для Каждого ЭлементИндекса Из ИндексПодписчиков Цикл + Для Каждого Подписчик Из ПодписчикиПоПриоритету() Цикл - Подписчик = ЭлементИндекса.Значение; - Подписчик.ВыполнитьПодписку(ИмяПроцедурыВыполнения, ПараметрыПроцедуры); КонецЦикла; КонецПроцедуры +Функция ПодписчикиПоПриоритету() + Таблица = Новый ТаблицаЗначений; + Таблица.Колонки.Добавить("Приоритет", Новый ОписаниеТипов("Число")); + Таблица.Колонки.Добавить("Подписчик"); + Для Каждого ЭлементИндекса Из ИндексПодписчиков Цикл + Стр = Таблица.Добавить(); + Стр.Приоритет = ЭлементИндекса.Значение.Приоритет(); + Стр.Подписчик = ЭлементИндекса.Значение; + КонецЦикла; + Таблица.Сортировать("Приоритет Убыв"); + Результат = Новый Массив; + Для Каждого Стр Из Таблица Цикл + Результат.Добавить(Стр.Подписчик); + КонецЦикла; + Возврат Результат; +КонецФункции + Процедура ПрисвоитьЗначенияПараметраПроцедуры(НовыеЗначения, // BSLLS:NumberOfParams-off Перем0 = Неопределено, Перем1 = Неопределено, From 0ef2d2eb27521ea4264ee645b2894884b6def1f2 Mon Sep 17 00:00:00 2001 From: Igor Storozhuk Date: Mon, 15 Jun 2026 14:39:38 +0300 Subject: [PATCH 2/2] =?UTF-8?q?=D0=A2=D0=B5=D1=81=D1=82=D1=8B=20=D1=81?= =?UTF-8?q?=D0=BE=D1=80=D1=82=D0=B8=D1=80=D0=BE=D0=B2=D0=BA=D0=B8=20=D0=BF?= =?UTF-8?q?=D0=BB=D0=B0=D0=B3=D0=B8=D0=BD=D0=BE=D0=B2=20=D0=BF=D0=BE=20?= =?UTF-8?q?=D0=9F=D1=80=D0=B8=D0=BE=D1=80=D0=B8=D1=82=D0=B5=D1=82()=20?= =?UTF-8?q?=D0=B2=20=D0=9C=D0=B5=D0=BD=D0=B5=D0=B4=D0=B6=D0=B5=D1=80=D0=9F?= =?UTF-8?q?=D0=BE=D0=B4=D0=BF=D0=B8=D1=81=D0=BE=D0=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - tests/fixtures/СтабПодписчик.os: минимальный стаб с Приоритет() и ВыполнитьПодписку(), получает журнал вызовов по ссылке из теста - tests/МенеджерПодписок_сортировка_test.os: 5 тестов на детерминированный порядок вызова: 2 подписчика, 3 подписчика с перепутанными приоритетами, 1 подписчик, пустой индекс Co-Authored-By: Claude Sonnet 4.6 --- tests/fixtures/lib.config | 4 + ...20\270\321\201\321\207\320\270\320\272.os" | 21 +++ ...0\320\276\320\262\320\272\320\260_test.os" | 144 ++++++++++++++++++ 3 files changed, 169 insertions(+) create mode 100644 tests/fixtures/lib.config create mode 100644 "tests/fixtures/\320\241\321\202\320\260\320\261\320\237\320\276\320\264\320\277\320\270\321\201\321\207\320\270\320\272.os" create mode 100644 "tests/\320\234\320\265\320\275\320\265\320\264\320\266\320\265\321\200\320\237\320\276\320\264\320\277\320\270\321\201\320\276\320\272_\321\201\320\276\321\200\321\202\320\270\321\200\320\276\320\262\320\272\320\260_test.os" diff --git a/tests/fixtures/lib.config b/tests/fixtures/lib.config new file mode 100644 index 00000000..dc17ae7a --- /dev/null +++ b/tests/fixtures/lib.config @@ -0,0 +1,4 @@ + + + + diff --git "a/tests/fixtures/\320\241\321\202\320\260\320\261\320\237\320\276\320\264\320\277\320\270\321\201\321\207\320\270\320\272.os" "b/tests/fixtures/\320\241\321\202\320\260\320\261\320\237\320\276\320\264\320\277\320\270\321\201\321\207\320\270\320\272.os" new file mode 100644 index 00000000..afecdfc6 --- /dev/null +++ "b/tests/fixtures/\320\241\321\202\320\260\320\261\320\237\320\276\320\264\320\277\320\270\321\201\321\207\320\270\320\272.os" @@ -0,0 +1,21 @@ +// Минимальный стаб подписчика для тестирования МенеджерПодписок. +// Реализует интерфейс ИндексПодписчиков: Приоритет() и ВыполнитьПодписку(). +// ЖурналВызовов — массив, переданный по ссылке из теста; стаб пишет в него свою метку при каждом вызове. + +Перем _Приоритет; +Перем _Метка; +Перем _ЖурналВызовов; + +Процедура Инициализировать(Знач Приоритет, Знач Метка, Знач ЖурналВызовов) Экспорт + _Приоритет = Приоритет; + _Метка = Метка; + _ЖурналВызовов = ЖурналВызовов; +КонецПроцедуры + +Функция Приоритет() Экспорт + Возврат _Приоритет; +КонецФункции + +Процедура ВыполнитьПодписку(ИмяПроцедуры, Параметры) Экспорт + _ЖурналВызовов.Добавить(_Метка); +КонецПроцедуры diff --git "a/tests/\320\234\320\265\320\275\320\265\320\264\320\266\320\265\321\200\320\237\320\276\320\264\320\277\320\270\321\201\320\276\320\272_\321\201\320\276\321\200\321\202\320\270\321\200\320\276\320\262\320\272\320\260_test.os" "b/tests/\320\234\320\265\320\275\320\265\320\264\320\266\320\265\321\200\320\237\320\276\320\264\320\277\320\270\321\201\320\276\320\272_\321\201\320\276\321\200\321\202\320\270\321\200\320\276\320\262\320\272\320\260_test.os" new file mode 100644 index 00000000..b28ab0f0 --- /dev/null +++ "b/tests/\320\234\320\265\320\275\320\265\320\264\320\266\320\265\321\200\320\237\320\276\320\264\320\277\320\270\321\201\320\276\320\272_\321\201\320\276\321\200\321\202\320\270\321\200\320\276\320\262\320\272\320\260_test.os" @@ -0,0 +1,144 @@ +// Запуск (из корня репозитория): +// oscript -encoding=utf-8 "%ONESCRIPT_LIB%\1testrunner\src\main.os" tests\МенеджерПодписок_сортировка_test.os + +#использовать "../src/core/" +#Использовать "./fixtures" +#Использовать asserts +#Использовать logos + +Перем Лог; + +Функция ПолучитьСписокТестов(Знач Тестирование) Экспорт + + ИменаТестов = Новый Массив; + ИменаТестов.Добавить("ТестДолжен_ВызыватьПодписчиковВПорядкеУбыванияПриоритета"); + ИменаТестов.Добавить("ТестДолжен_ВызыватьВсехПодписчиков"); + ИменаТестов.Добавить("ТестДолжен_ВызыватьТрёхПодписчиковВПравильномПорядке"); + ИменаТестов.Добавить("ТестДолжен_КорректноОбрабатыватьОдногоПодписчика"); + ИменаТестов.Добавить("ТестДолжен_НеВызыватьЕслиПустойИндекс"); + + Возврат ИменаТестов; + +КонецФункции + +Процедура ПередЗапускомТестов() Экспорт + Лог = Логирование.ПолучитьЛог("test.менеджер-подписок"); +КонецПроцедуры + +Процедура ПослеЗапускаТестов() Экспорт +КонецПроцедуры + +// =========================================================================== + +// А(приоритет=100) должна быть вызвана раньше Б(приоритет=0) +Процедура ТестДолжен_ВызыватьПодписчиковВПорядкеУбыванияПриоритета() Экспорт + + Журнал = Новый Массив; + + А = Новый СтабПодписчик; + А.Инициализировать(100, "А", Журнал); + + Б = Новый СтабПодписчик; + Б.Инициализировать(0, "Б", Журнал); + + МенеджерПодписок = Новый МенеджерПодписок; + МенеджерПодписок.УстановитьПодписчиков(СоздатьИндекс("А", А, "Б", Б)); + МенеджерПодписок.ПослеКоммита("", ""); + + Ожидаем.Что(Журнал[0], "Первой вызвана А (приоритет 100)").Равно("А"); + Ожидаем.Что(Журнал[1], "Второй вызвана Б (приоритет 0)").Равно("Б"); + +КонецПроцедуры + +// Все подписчики должны быть вызваны, не только первый +Процедура ТестДолжен_ВызыватьВсехПодписчиков() Экспорт + + Журнал = Новый Массив; + + А = Новый СтабПодписчик; + А.Инициализировать(100, "А", Журнал); + + Б = Новый СтабПодписчик; + Б.Инициализировать(0, "Б", Журнал); + + МенеджерПодписок = Новый МенеджерПодписок; + МенеджерПодписок.УстановитьПодписчиков(СоздатьИндекс("А", А, "Б", Б)); + МенеджерПодписок.ПослеКоммита("", ""); + + Ожидаем.Что(Журнал.Количество(), "Вызваны оба подписчика").Равно(2); + +КонецПроцедуры + +// Три подписчика с перепутанными приоритетами — порядок по убыванию: В(50), А(10), Б(1) +Процедура ТестДолжен_ВызыватьТрёхПодписчиковВПравильномПорядке() Экспорт + + Журнал = Новый Массив; + + А = Новый СтабПодписчик; + А.Инициализировать(10, "А", Журнал); + + Б = Новый СтабПодписчик; + Б.Инициализировать(1, "Б", Журнал); + + В = Новый СтабПодписчик; + В.Инициализировать(50, "В", Журнал); + + Индекс = Новый Соответствие; + Индекс.Вставить("А", А); + Индекс.Вставить("Б", Б); + Индекс.Вставить("В", В); + + МенеджерПодписок = Новый МенеджерПодписок; + МенеджерПодписок.УстановитьПодписчиков(Индекс); + МенеджерПодписок.ПослеКоммита("", ""); + + Ожидаем.Что(Журнал.Количество(), "Вызваны все три подписчика").Равно(3); + Ожидаем.Что(Журнал[0], "Первой вызвана В (приоритет 50)").Равно("В"); + Ожидаем.Что(Журнал[1], "Второй вызвана А (приоритет 10)").Равно("А"); + Ожидаем.Что(Журнал[2], "Третьей вызвана Б (приоритет 1)").Равно("Б"); + +КонецПроцедуры + +// Один подписчик — должен быть вызван без ошибок +Процедура ТестДолжен_КорректноОбрабатыватьОдногоПодписчика() Экспорт + + Журнал = Новый Массив; + + А = Новый СтабПодписчик; + А.Инициализировать(42, "А", Журнал); + + МенеджерПодписок = Новый МенеджерПодписок; + МенеджерПодписок.УстановитьПодписчиков(СоздатьИндекс("А", А)); + МенеджерПодписок.ПослеКоммита("", ""); + + Ожидаем.Что(Журнал.Количество(), "Единственный подписчик вызван").Равно(1); + Ожидаем.Что(Журнал[0]).Равно("А"); + +КонецПроцедуры + +// Пустой индекс — никаких вызовов, никаких исключений +Процедура ТестДолжен_НеВызыватьЕслиПустойИндекс() Экспорт + + Журнал = Новый Массив; + + МенеджерПодписок = Новый МенеджерПодписок; + МенеджерПодписок.УстановитьПодписчиков(Новый Соответствие); + МенеджерПодписок.ПослеКоммита("", ""); + + Ожидаем.Что(Журнал.Количество(), "Подписчики не вызывались").Равно(0); + +КонецПроцедуры + +// =========================================================================== +// Вспомогательные +// =========================================================================== + +Функция СоздатьИндекс(Знач К1 = "", Знач В1 = Неопределено, + Знач К2 = "", Знач В2 = Неопределено) + Индекс = Новый Соответствие; + Если Не ПустаяСтрока(К1) Тогда Индекс.Вставить(К1, В1); КонецЕсли; + Если Не ПустаяСтрока(К2) Тогда Индекс.Вставить(К2, В2); КонецЕсли; + Возврат Индекс; +КонецФункции + +Лог = Логирование.ПолучитьЛог("test.менеджер-подписок");