-
Notifications
You must be signed in to change notification settings - Fork 119
Expand file tree
/
Copy pathnative-api.os
More file actions
624 lines (476 loc) · 38.2 KB
/
Copy pathnative-api.os
File metadata and controls
624 lines (476 loc) · 38.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
Перем юТест;
Перем ЭтоWindows;
Перем DLLПодключенаУспешно;
Перем ЗаписьXML, ЗаписьZIP, КаталогСкрипта, КаталогПакета, СуффиксВерсии;
Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт
ПроверитьСуществованиеПрокси();
юТест = ЮнитТестирование;
ВсеТесты = Новый Массив;
// TODO: сделать прогон этого теста еще и на 32-битной архитектуре, см. ошибку #1531
ВсеТесты.Добавить("ТестДолжен_ПроверитьПодключениеВнешнейКомпонентыZIP");
ВсеТесты.Добавить("ТестДолжен_ПроверитьПодключениеВнешнейКомпонентыDLL");
ВсеТесты.Добавить("ТестДолжен_ПроверитьСвойстваВнешнейКомпоненты");
ВсеТесты.Добавить("ТестДолжен_ПроверитьМетодыВнешнейКомпоненты");
ВсеТесты.Добавить("ТестДолжен_ПроверитьОбменПараметров");
ВсеТесты.Добавить("ТестДолжен_ПроверитьОбменДатойVTYPE_TM");
ВсеТесты.Добавить("ТестДолжен_ВыдержатьСборкуМусораПриКолбэкеОшибки");
ВсеТесты.Добавить("ТестДолжен_ОтклонитьПрямойАлиас");
ВсеТесты.Добавить("ТестДолжен_ОтклонитьНесуществующийКласс");
ВсеТесты.Добавить("ТестДолжен_СоздатьКомпонентуНезависимоОтРегистра");
ВсеТесты.Добавить("ТестДолжен_ОтклонитьНеподключённуюМетку");
ВсеТесты.Добавить("ТестДолжен_СоздатьКомпонентуПоRegisterExtensionAs");
ВсеТесты.Добавить("ТестДолжен_ИспользоватьКэшRegisterExtensionAs");
ВсеТесты.Добавить("ТестДолжен_СоздатьSecondAddInНезависимоОтРегистра");
ВсеТесты.Добавить("ТестДолжен_ОтклонитьКлючФабрикиGetClassNames");
ВсеТесты.Добавить("ТестДолжен_БалансироватьСчётчикиЖизненногоЦикла");
#Если Windows Тогда
ЭтоWindows = Истина;
#ИначеЕсли Linux Тогда
ЭтоWindows = Ложь;
#Иначе
Возврат Новый Массив; // под макос не тестируем
#КонецЕсли
Возврат ВсеТесты;
КонецФункции
Процедура ПроверитьСуществованиеПрокси()
Каталог = КаталогПрограммы();
СистемнаяИнформация = Новый СистемнаяИнформация();
Если СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86 Тогда
ПутьБиблиотеки = ОбъединитьПути(Каталог, "ScriptEngine.NativeApi32.dll");
ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86_64 Тогда
ПутьБиблиотеки = ОбъединитьПути(Каталог, "ScriptEngine.NativeApi64.dll");
ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Linux_x86 Тогда
ПутьБиблиотеки = ОбъединитьПути(Каталог, "ScriptEngine.NativeApi32.so");
ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Linux_x86_64 Тогда
ПутьБиблиотеки = ОбъединитьПути(Каталог, "ScriptEngine.NativeApi64.so");
Иначе
ПутьБиблиотеки = "";
КонецЕсли;
Сборка = Новый Файл(ПутьБиблиотеки);
Если Не Сборка.Существует() Тогда
ВызватьИсключение СтрШаблон("Не собрана прокси-библиотека для NativeApi: %1", ПутьБиблиотеки);
КонецЕсли;
КонецПроцедуры
Функция ПодключитьКомпонентуDLL()
Если DLLПодключенаУспешно <> Неопределено Тогда
Возврат DLLПодключенаУспешно;
КонецЕсли;
СистемнаяИнформация = Новый СистемнаяИнформация();
КаталогСборок = ОбъединитьПути(ТекущийСценарий().Каталог, "native-api");
Если СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86 Тогда
ПутьБиблиотеки = ОбъединитьПути(КаталогСборок, "bin", "AddInNativeWin32.dll");
ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Windows_x86_64 Тогда
ПутьБиблиотеки = ОбъединитьПути(КаталогСборок, "bin64", "AddInNativeWin64.dll");
ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Linux_x86 Тогда
ПутьБиблиотеки = ОбъединитьПути(КаталогСборок, "build32", "AddInNativeLin32.so");
ИначеЕсли СистемнаяИнформация.ТипПлатформы = ТипПлатформы.Linux_x86_64 Тогда
ПутьБиблиотеки = ОбъединитьПути(КаталогСборок, "build64", "AddInNativeLin64.so");
Иначе
ВызватьИсключение "Неподдерживаемый тип платформы: " + СистемнаяИнформация.ТипПлатформы;
КонецЕсли;
Идентификатор = "AddinNativeDLL";
ФайлКомпоненты = Новый Файл(ПутьБиблиотеки);
юТест.ПроверитьИстину(ФайлКомпоненты.Существует(),
"Файл компоненты '" + ФайлКомпоненты.ПолноеИмя + "' должен существовать");
DLLПодключенаУспешно = ПодключитьВнешнююКомпоненту(ФайлКомпоненты.ПолноеИмя, Идентификатор, ТипВнешнейКомпоненты.Native);
Возврат DLLПодключенаУспешно;
КонецФункции
Процедура ТестДолжен_ПроверитьПодключениеВнешнейКомпонентыZIP() Экспорт
ИмяФайлаПакета = юТест.ИмяВременногоФайла();
ЗаписьZIP = Новый ЗаписьZipФайла(ИмяФайлаПакета);
МасивФайлов = Новый Массив;
Если ЭтоWindows Тогда
Каталог = ТекущийСценарий().Каталог + "\native-api\";
МасивФайлов.Добавить("bin\AddInNativeWin32.dll");
МасивФайлов.Добавить("bin64\AddInNativeWin64.dll");
Иначе
Каталог = ТекущийСценарий().Каталог + "/native-api/";
МасивФайлов.Добавить("build32/AddInNativeLin32.so");
МасивФайлов.Добавить("build64/AddInNativeLin64.so");
КонецЕсли;
ЗаписьZIP.Добавить(Каталог + "MANIFEST.XML", РежимСохраненияПутейZIP.НеСохранятьПути);
Для каждого ИмяФайла из МасивФайлов Цикл
ПутьФайла = Каталог + ИмяФайла;
Файл = Новый Файл(ПутьФайла);
Если Файл.Существует() Тогда
ЗаписьZIP.Добавить(ПутьФайла, РежимСохраненияПутейZIP.НеСохранятьПути);
КонецЕсли;
КонецЦикла;
ЗаписьZIP.Записать();
Идентификатор = "AddinNativeZip";
Успешно = ПодключитьВнешнююКомпоненту(ИмяФайлаПакета, Идентификатор, ТипВнешнейКомпоненты.Native);
юТест.ПроверитьРавенство(Успешно, Истина);
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".CAddInNative";
ВнешняяКомпонента = Новый(ИмяВнешнейКомпоненты);
юТест.ПроверитьРавенство(Строка(ТипЗнч(ВнешняяКомпонента)), Строка(Тип(ИмяВнешнейКомпоненты)));
КонецПроцедуры
Процедура ТестДолжен_ПроверитьПодключениеВнешнейКомпонентыDLL() Экспорт
Идентификатор = "AddinNativeDLL";
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".CAddInNative";
ВнешняяКомпонента = Новый(ИмяВнешнейКомпоненты);
ВнешняяКомпонента.Включить();
юТест.ПроверитьРавенство(ВнешняяКомпонента.Включен, Истина);
ВнешняяКомпонента.Выключить();
юТест.ПроверитьРавенство(ВнешняяКомпонента.Включен, Ложь);
КонецПроцедуры
Процедура ТестДолжен_ПроверитьСвойстваВнешнейКомпоненты() Экспорт
Идентификатор = "AddinNativeDLL";
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".CAddInNative";
ВнешняяКомпонента = Новый(ИмяВнешнейКомпоненты);
ВнешняяКомпонента.Включен = Истина;
юТест.ПроверитьРавенство(ВнешняяКомпонента.Включен, Истина);
юТест.ПроверитьРавенство(ВнешняяКомпонента.IsEnabled, Истина);
ВнешняяКомпонента.Включен = Ложь;
юТест.ПроверитьРавенство(ВнешняяКомпонента.Включен, Ложь);
юТест.ПроверитьРавенство(ВнешняяКомпонента.IsEnabled, Ложь);
ВнешняяКомпонента["Включен"] = Истина;
юТест.ПроверитьРавенство(ВнешняяКомпонента["Включен"], Истина);
юТест.ПроверитьРавенство(ВнешняяКомпонента["IsEnabled"], Истина);
СодержимоеСтроки = "Тест строки только на запись";
ВнешняяКомпонента.СтрокаТолькоЗапись = СодержимоеСтроки;
юТест.ПроверитьРавенство(ВнешняяКомпонента.СтрокаЧтениеЗапись, СодержимоеСтроки);
юТест.ПроверитьРавенство(ВнешняяКомпонента.СтрокаТолькоЧтение, СодержимоеСтроки);
СодержимоеСтроки = "Тест строки на чтение и запись";
ВнешняяКомпонента.СтрокаЧтениеЗапись = СодержимоеСтроки;
юТест.ПроверитьРавенство(ВнешняяКомпонента.СтрокаЧтениеЗапись, СодержимоеСтроки);
юТест.ПроверитьРавенство(ВнешняяКомпонента.СтрокаТолькоЧтение, СодержимоеСтроки);
Попытка
ВнешняяКомпонента.СтрокаТолькоЧтение = СодержимоеСтроки;
юТест.ТестПровален("Удалось изменить недоступное для записи свойство");
Исключение
юТест.ТестПройден();
КонецПопытки;
Попытка
СодержимоеСтроки = ВнешняяКомпонента.СтрокаТолькоЗапись;
юТест.ТестПровален("Удалось прочитать недоступное для чтения свойство");
Исключение
юТест.ТестПройден();
КонецПопытки;
Попытка
ВнешняяКомпонента.СвойствоОтсутствует = СодержимоеСтроки;
юТест.ТестПровален("Удалось обратиться к отсутствующему свойству");
Исключение
юТест.ТестПройден();
КонецПопытки;
КонецПроцедуры
Процедура ТестДолжен_ПроверитьМетодыВнешнейКомпоненты() Экспорт
Идентификатор = "AddinNativeDLL";
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".CAddInNative";
ВнешняяКомпонента = Новый(ИмяВнешнейКомпоненты);
ВнешняяКомпонента.Включить();
юТест.ПроверитьРавенство(ВнешняяКомпонента.Включен, Истина);
ВнешняяКомпонента.Выключить();
юТест.ПроверитьРавенство(ВнешняяКомпонента.Включен, Ложь);
Попытка
ВнешняяКомпонента.Выключить(Истина);
юТест.ТестПровален("Удалось передать параметр в метод без параметров");
Исключение
юТест.ТестПройден();
КонецПопытки;
юТест.ПроверитьРавенство(ВнешняяКомпонента.ПараметрПоУмолчанию(), Истина);
юТест.ПроверитьРавенство(ВнешняяКомпонента.ПараметрПоУмолчанию(Ложь), Ложь);
Попытка
Значение = ВнешняяКомпонента.ПараметрПоУмолчанию(Истина, Ложь);
юТест.ТестПровален("Удалось передать лишний параметр в метод с одним параметром");
Исключение
юТест.ТестПройден();
КонецПопытки;
ПерваяСтрока = "Первая строка";
ВтораяСтрока = "Вторая тестовая строка";
КонкатенацияСтрок = ВнешняяКомпонента.КонкатенацияСтрок(ПерваяСтрока, ВтораяСтрока);
юТест.ПроверитьРавенство(КонкатенацияСтрок, ПерваяСтрока + ВтораяСтрока);
СодержимоеФайла = "Тест двоичных данных";
ВременныйФайл = юТест.ИмяВременногоФайла();
ЗаписьТекста = Новый ЗаписьТекста(ВременныйФайл, КодировкаТекста.UTF8);
ЗаписьТекста.Записать(СодержимоеФайла);
ЗаписьТекста.Закрыть();
ДвоичныеДанные = Новый ДвоичныеДанные(ВременныйФайл);
ДвоичныеДанные = ВнешняяКомпонента.Петля(ДвоичныеДанные);
Поток = ДвоичныеДанные.ОткрытьПотокДляЧтения();
ЧтениеТекста = Новый ЧтениеТекста(Поток, КодировкаТекста.UTF8);
юТест.ПроверитьРавенство(ЧтениеТекста.Прочитать(), СодержимоеФайла);
КонецПроцедуры
Процедура ТестДолжен_ПроверитьОбменПараметров() Экспорт
Идентификатор = "AddinNativeDLL";
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".CAddInNative";
ВнешняяКомпонента = Новый(ИмяВнешнейКомпоненты);
// 1. Обмен строковых out-параметров
А = "Первый";
Б = "Второй";
ВнешняяКомпонента.ОбменПараметров(А, Б);
юТест.ПроверитьРавенство(А, "Второй");
юТест.ПроверитьРавенство(Б, "Первый");
// 2. Обмен числовых out-параметров
Число1 = 1;
Число2 = 2;
ВнешняяКомпонента.ОбменПараметров(Число1, Число2);
юТест.ПроверитьРавенство(Число1, 2);
юТест.ПроверитьРавенство(Число2, 1);
// 3. Компонента не меняет параметр — переменная сохраняется
Значение = "без изменений";
ВнешняяКомпонента.ПропуститьПараметры(Значение);
юТест.ПроверитьРавенство(Значение, "без изменений");
// Подготовка read-only свойства компоненты
ВнешняяКомпонента.СтрокаТолькоЗапись = "исходное значение RO";
// 4. Read-only свойство без изменения параметра — без исключения
ВнешняяКомпонента.ПропуститьПараметры(ВнешняяКомпонента.СтрокаТолькоЧтение);
юТест.ПроверитьРавенство(ВнешняяКомпонента.СтрокаТолькоЧтение, "исходное значение RO");
// 5. Компонента меняет read-only свойство — штатное исключение о записи
Запись = "запись";
Попытка
ВнешняяКомпонента.ОбменПараметров(ВнешняяКомпонента.СтрокаТолькоЧтение, Запись);
юТест.ТестПровален("Ожидалось исключение при записи в read-only свойство");
Исключение
юТест.ПроверитьИстину(
СтрНайти(ОписаниеОшибки(), "недоступно для записи") > 0,
"Ожидалось исключение о недоступности свойства для записи");
КонецПопытки;
// 6. Литерал, константа и результат выражения — без исключения
ВнешняяКомпонента.ПропуститьПараметры("литерал");
ВнешняяКомпонента.ПропуститьПараметры(Истина);
ВнешняяКомпонента.ПропуститьПараметры("часть" + "выражения");
// 7. Пропущенный параметр по умолчанию — обратная запись не выполняется
Параметр = Ложь;
Результат = ВнешняяКомпонента.ПараметрПоУмолчанию(Параметр);
юТест.ПроверитьРавенство(Результат, Ложь);
юТест.ПроверитьРавенство(Параметр, Ложь);
юТест.ПроверитьРавенство(ВнешняяКомпонента.ПараметрПоУмолчанию(), Истина);
// 8. Обмен параметров разных типов
Булево1 = Истина;
Булево2 = Ложь;
ВнешняяКомпонента.ОбменПараметров(Булево1, Булево2);
юТест.ПроверитьРавенство(Булево1, Ложь);
юТест.ПроверитьРавенство(Булево2, Истина);
Дата1 = Дата(2024, 1, 15, 10, 20, 30);
Дата2 = Дата(2024, 6, 1, 0, 0, 0);
ВнешняяКомпонента.ОбменПараметров(Дата1, Дата2);
юТест.ПроверитьРавенство(Дата1, Дата(2024, 6, 1, 0, 0, 0));
юТест.ПроверитьРавенство(Дата2, Дата(2024, 1, 15, 10, 20, 30));
Содержимое1 = "данные А";
Содержимое2 = "данные Б";
Файл1 = юТест.ИмяВременногоФайла();
Файл2 = юТест.ИмяВременногоФайла();
ЗаписьТекста = Новый ЗаписьТекста(Файл1, КодировкаТекста.UTF8);
ЗаписьТекста.Записать(Содержимое1);
ЗаписьТекста.Закрыть();
ЗаписьТекста = Новый ЗаписьТекста(Файл2, КодировкаТекста.UTF8);
ЗаписьТекста.Записать(Содержимое2);
ЗаписьТекста.Закрыть();
Двоичные1 = Новый ДвоичныеДанные(Файл1);
Двоичные2 = Новый ДвоичныеДанные(Файл2);
ВнешняяКомпонента.ОбменПараметров(Двоичные1, Двоичные2);
Поток1 = Двоичные1.ОткрытьПотокДляЧтения();
Чтение1 = Новый ЧтениеТекста(Поток1, КодировкаТекста.UTF8);
юТест.ПроверитьРавенство(Чтение1.Прочитать(), Содержимое2);
Поток2 = Двоичные2.ОткрытьПотокДляЧтения();
Чтение2 = Новый ЧтениеТекста(Поток2, КодировкаТекста.UTF8);
юТест.ПроверитьРавенство(Чтение2.Прочитать(), Содержимое1);
// 9. Неуспешный вызов (CallAsProc = false) не переносит out-параметры в скрипт.
// Метод ОшибкаПослеИзменения внутри компоненты меняет числовой параметр (10 -> 11)
// в массиве tVariant, но возвращает false — вызов считается неуспешным.
// Обёртка OneScript не должна вызывать RemapOutputParameters и оставлять
// исходное значение переменной без изменений.
Число = 10;
ВнешняяКомпонента.ОшибкаПослеИзменения(Число);
юТест.ПроверитьРавенство(Число, 10);
КонецПроцедуры
Процедура ТестДолжен_ПроверитьОбменДатойVTYPE_TM() Экспорт
Идентификатор = "AddinNativeDLL";
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".CAddInNative";
ВнешняяКомпонента = Новый(ИмяВнешнейКомпоненты);
ИсходнаяДата = Дата(2024, 2, 29, 23, 59, 58);
ВнешняяКомпонента.ФиксированнаяДата = ИсходнаяДата;
ДатаИзСвойства = ВнешняяКомпонента.FixedDate;
юТест.ПроверитьРавенство(
ТипЗнч(ДатаИзСвойства), Тип("Дата"),
"Свойство FixedDate должно иметь тип Дата");
юТест.ПроверитьРавенство(ДатаИзСвойства, ИсходнаяДата);
РезультатЭхо = ВнешняяКомпонента.ЭхоДатаTM(ДатаИзСвойства);
юТест.ПроверитьРавенство(
ТипЗнч(РезультатЭхо), Тип("Дата"),
"Результат EchoDateTm должен иметь тип Дата");
юТест.ПроверитьРавенство(РезультатЭхо, ДатаИзСвойства);
РезультатDATE = ВнешняяКомпонента.ПолучитьДатуКакVTYPE_DATE();
юТест.ПроверитьРавенство(РезультатDATE, ИсходнаяДата);
юТест.ПроверитьРавенство(ДатаИзСвойства, РезультатDATE);
// Минимальная дата языка
МинимальнаяДата = Дата(1, 1, 1);
ВнешняяКомпонента.ФиксированнаяДата = МинимальнаяДата;
юТест.ПроверитьРавенство(ВнешняяКомпонента.FixedDate, МинимальнаяДата);
// Секунды около перехода через полночь
ДатаПередПолуночью = Дата(2024, 3, 1, 0, 0, 1);
ВнешняяКомпонента.ФиксированнаяДата = ДатаПередПолуночью;
юТест.ПроверитьРавенство(ВнешняяКомпонента.FixedDate, ДатаПередПолуночью);
ДатаПослеПолуночи = Дата(2024, 2, 29, 23, 59, 59);
ВнешняяКомпонента.ФиксированнаяДата = ДатаПослеПолуночи;
юТест.ПроверитьРавенство(ВнешняяКомпонента.FixedDate, ДатаПослеПолуночи);
// Дополнительная дата из характеристического набора
ДополнительнаяДата = Дата(2024, 6, 15, 12, 30, 45);
ВнешняяКомпонента.ФиксированнаяДата = ДополнительнаяДата;
юТест.ПроверитьРавенство(ВнешняяКомпонента.FixedDate, ДополнительнаяДата);
// Некорректные значения от компоненты
Попытка
ВнешняяКомпонента.ПолучитьНекорректнуюДатуКакVTYPE_DATE();
юТест.ТестПровален("Ожидалось исключение для некорректного VTYPE_DATE");
Исключение
юТест.ПроверитьИстину(
СтрНайти(ОписаниеОшибки(), "VTYPE_DATE") > 0,
"Сообщение об ошибке должно указывать VTYPE_DATE");
КонецПопытки;
Попытка
ВнешняяКомпонента.ПолучитьНекорректнуюДатуКакVTYPE_TM();
юТест.ТестПровален("Ожидалось исключение для некорректного VTYPE_TM");
Исключение
юТест.ПроверитьИстину(
СтрНайти(ОписаниеОшибки(), "VTYPE_TM") > 0,
"Сообщение об ошибке должно указывать VTYPE_TM");
КонецПопытки;
КонецПроцедуры
Процедура ТестДолжен_ВыдержатьСборкуМусораПриКолбэкеОшибки() Экспорт
// Регрессия issue #1359: нативный код хранит указатели на managed-делегаты колбэков.
// После GC без закрепления делегатов следующий AddError из компоненты роняет процесс.
Идентификатор = "AddinNativeDLL";
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".CAddInNative";
ВнешняяКомпонента = Новый(ИмяВнешнейКомпоненты);
КоличествоИтераций = 100;
Счетчик = 0;
Для Номер = 1 По КоличествоИтераций Цикл
ВыполнитьСборкуМусора();
Попытка
// Неверный тип параметра → addError → колбэк OnError из нативного кода
ВнешняяКомпонента.Петля("строка вместо двоичных данных");
Исключение
КонецПопытки;
Счетчик = Счетчик + 1;
КонецЦикла;
юТест.ПроверитьРавенство(Счетчик, КоличествоИтераций);
КонецПроцедуры
Процедура ТестДолжен_ОтклонитьПрямойАлиас() Экспорт
Идентификатор = "AddinNativeDLL";
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".DirectAlias";
Попытка
ВнешняяКомпонента = Новый(ИмяВнешнейКомпоненты);
юТест.ТестПровален("Ожидалось исключение при создании по прямому алиасу GetClassObject");
Исключение
юТест.ПроверитьИстину(
СтрНайти(ОписаниеОшибки(), "DirectAlias") > 0,
"Сообщение об ошибке должно содержать имя класса");
КонецПопытки;
КонецПроцедуры
Процедура ТестДолжен_ОтклонитьНесуществующийКласс() Экспорт
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяКласса = "ЗаведомоНетТакого";
ИмяТипа = "AddIn.AddinNativeDLL." + ИмяКласса;
Попытка
Компонента = Новый(ИмяТипа);
юТест.ТестПровален("Ожидалось исключение при создании несуществующего класса");
Исключение
ТекстОшибки = ОписаниеОшибки();
юТест.ПроверитьИстину(
СтрНайти(ТекстОшибки, ИмяКласса) > 0,
"Сообщение об ошибке должно содержать имя класса");
юТест.ПроверитьИстину(
СтрНайти(ТекстОшибки, "CAddInNative") > 0,
"Сообщение об ошибке должно перечислять доступные имена расширений");
юТест.ПроверитьИстину(
СтрНайти(ТекстОшибки, "SecondAddIn") > 0,
"Сообщение об ошибке должно перечислять доступные имена расширений");
КонецПопытки;
КонецПроцедуры
Процедура ТестДолжен_СоздатьКомпонентуНезависимоОтРегистра() Экспорт
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ВнешняяКомпонента = Новый("addin.addinnativedll.caddinnative");
ВнешняяКомпонента.Включить();
юТест.ПроверитьРавенство(ВнешняяКомпонента.Включен, Истина);
КонецПроцедуры
Процедура ТестДолжен_СоздатьКомпонентуПоRegisterExtensionAs() Экспорт
Идентификатор = "AddinNativeDLL";
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".SecondAddIn";
ВнешняяКомпонента = Новый(ИмяВнешнейКомпоненты);
ВнешняяКомпонента.Включить();
юТест.ПроверитьРавенство(ВнешняяКомпонента.Включен, Истина);
КонецПроцедуры
Процедура ТестДолжен_ИспользоватьКэшRegisterExtensionAs() Экспорт
Идентификатор = "AddinNativeDLL";
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn." + Идентификатор + ".SecondAddIn";
ПерваяКомпонента = Новый(ИмяВнешнейКомпоненты);
ВтораяКомпонента = Новый(ИмяВнешнейКомпоненты);
ВтораяКомпонента.Включить();
юТест.ПроверитьРавенство(ВтораяКомпонента.Включен, Истина);
юТест.ПроверитьРавенство(ТипЗнч(ПерваяКомпонента), Тип(ИмяВнешнейКомпоненты));
КонецПроцедуры
Процедура ТестДолжен_СоздатьSecondAddInНезависимоОтРегистра() Экспорт
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ВнешняяКомпонента = Новый("addin.addinnativedll.secondaddin");
ВнешняяКомпонента.Включить();
юТест.ПроверитьРавенство(ВнешняяКомпонента.Включен, Истина);
КонецПроцедуры
Процедура ТестДолжен_ОтклонитьКлючФабрикиGetClassNames() Экспорт
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяТипа = "AddIn.AddinNativeDLL.2";
Попытка
Компонента = Новый(ИмяТипа);
юТест.ТестПровален("Ожидалось исключение при создании по ключу фабрики GetClassNames");
Исключение
юТест.ПроверитьИстину(
СтрНайти(ОписаниеОшибки(), "2") > 0,
"Сообщение об ошибке должно содержать имя класса");
КонецПопытки;
КонецПроцедуры
Процедура ТестДолжен_БалансироватьСчётчикиЖизненногоЦикла() Экспорт
КомпонентаПодключена = ПодключитьКомпонентуDLL();
юТест.ПроверитьИстину(КомпонентаПодключена, "Компонента должна подключиться");
ИмяВнешнейКомпоненты = "AddIn.AddinNativeDLL.CAddInNative";
Зонд = Новый(ИмяВнешнейКомпоненты);
КонструкторовДо = Зонд.ПолучитьСчётчикКонструкторов();
ДеструкторовДо = Зонд.ПолучитьСчётчикДеструкторов();
КоличествоОбъектов = 20;
Для Номер = 1 По КоличествоОбъектов Цикл
Объект = Новый(ИмяВнешнейКомпоненты);
Объект = Неопределено;
ВыполнитьСборкуМусора();
КонецЦикла;
КонструкторовПосле = Зонд.ПолучитьСчётчикКонструкторов();
ДеструкторовПосле = Зонд.ПолучитьСчётчикДеструкторов();
юТест.ПроверитьРавенство(
КонструкторовПосле - КонструкторовДо,
КоличествоОбъектов,
"Каждый созданный объект должен увеличивать счётчик конструкторов");
юТест.ПроверитьРавенство(
ДеструкторовПосле,
ДеструкторовДо,
"Сборка мусора не должна вызывать деструкторы компоненты");
КонецПроцедуры
Процедура ТестДолжен_ОтклонитьНеподключённуюМетку() Экспорт
ИмяТипа = "AddIn.НетТакойМетки.Класс";
Попытка
Компонента = Новый(ИмяТипа);
юТест.ТестПровален("Ожидалось исключение при создании по неподключённой метке");
Исключение
юТест.ПроверитьИстину(
СтрНайти(ОписаниеОшибки(), "Тип не определен") > 0,
"Ожидалось исключение «Тип не определен»");
КонецПопытки;
КонецПроцедуры