Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions .github/workflows/incremental-dump.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: Incremental dump regression

on: [push, pull_request, workflow_dispatch]

permissions:
contents: read

jobs:
regression:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install OneScript 2.2.0
run: |
curl --fail --location --retry 3 https://github.com/EvilBeaver/OneScript/releases/download/v2.2.0/OneScript-2.2.0-linux-x64.zip -o "$RUNNER_TEMP/onescript.zip"
echo "3b3b0a96e141d6758b74cbf492d5e5c11823bfd92318caff1aaa19bd500f1df7 $RUNNER_TEMP/onescript.zip" | sha256sum --check
unzip -q "$RUNNER_TEMP/onescript.zip" -d "$RUNNER_TEMP/onescript"
chmod +x "$RUNNER_TEMP/onescript/bin/oscript"
echo "$RUNNER_TEMP/onescript/bin" >> "$GITHUB_PATH"
- name: Test without a 1C installation
run: |
oscript -version
python3 -B -m unittest discover -s tests -p test_incremental_dump.py -v
13 changes: 11 additions & 2 deletions src/v8runner.os
Original file line number Diff line number Diff line change
Expand Up @@ -728,7 +728,13 @@

Если ТолькоИзмененные Тогда

Если ПроверитьВозможностьОбновленияФайловВыгрузки(КаталогВыгрузки, ПутьКФайлуВерсийДляСравнения, ФорматВыгрузки) Тогда
ФайлВерсий = Новый Файл(ПутьКФайлуВерсийДляСравнения);
ФайлВерсийКаталога = Новый Файл(ОбъединитьПути(КаталогВыгрузки, "ConfigDumpInfo.xml"));
Если ФайлВерсий.ПолноеИмя = ФайлВерсийКаталога.ПолноеИмя Тогда
ПутьКФайлуВерсийДляСравнения = "";
КонецЕсли;

Если ПроверитьВозможностьОбновленияФайловВыгрузки(КаталогВыгрузки, ПутьКФайлуВерсийДляСравнения, ФорматВыгрузки, Истина) Тогда

Параметры.Добавить("-update");

Expand Down Expand Up @@ -2867,7 +2873,8 @@

// Функция проверяет возможность обновления файлов выгрузки, для каталога или конкретного файла версий
//
Функция ПроверитьВозможностьОбновленияФайловВыгрузки(Знач КаталогВыгрузки, Знач ПутьКФайлуВерсийДляСравнения = "", Знач ФорматВыгрузки = "")
Функция ПроверитьВозможностьОбновленияФайловВыгрузки(Знач КаталогВыгрузки, Знач ПутьКФайлуВерсийДляСравнения = "", Знач ФорматВыгрузки = "",
Знач ПустойОтветРазрешаетОбновление = Ложь)

ПутьКФайлуИзменений = ВременныеФайлы.НовоеИмяФайла();
ОбновлениеВозможно = Ложь;
Expand All @@ -2893,6 +2900,8 @@
Лог.Отладка("Строка проверки на возможность выгрузки конфигурации: <%1> = <%2> ", СтрокаПолныйДамп, СтрокаВыгрузки);
ОбновлениеВозможно = НЕ (СтрокаВыгрузки = СтрокаПолныйДамп);

Иначе
ОбновлениеВозможно = ПустойОтветРазрешаетОбновление И мИсключениеПриОшибкеВыполненияКоманды;
КонецЕсли;
чтениеФайла.Закрыть();

Expand Down
141 changes: 141 additions & 0 deletions tests/test_incremental_dump.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
import os
from pathlib import Path
import shutil
import subprocess
import tempfile
import unittest


SOURCE = Path(__file__).resolve().parents[1] / 'src' / 'v8runner.os'


@unittest.skipUnless(shutil.which('oscript'), 'OneScript is required')
class IncrementalDumpTest(unittest.TestCase):
def check_response(self, response, expected, versions=True, explicit=False,
raise_errors=True, allow_empty=True):
source = SOURCE.read_text(encoding='utf-8-sig')
start = source.index('Функция ПроверитьВозможностьОбновленияФайловВыгрузки(')
end = source.index('КонецФункции', start) + len('КонецФункции')
with tempfile.TemporaryDirectory(prefix='v8runner-incremental-') as directory:
root = Path(directory)
if versions:
(root / 'ConfigDumpInfo.xml').touch()
reference = root / ('ConfigDumpInfo.xml' if versions else 'reference.xml')
if explicit:
reference.touch()
if response is not None:
(root / 'response.txt').write_bytes(response)
harness = '''#Использовать tempfiles
#Использовать logos
Перем Лог;
Перем мИсключениеПриОшибкеВыполненияКоманды;

Процедура ВыгрузитьИзмененияКонфигурацииВФайл(Каталог, Путь, Версии, Формат)
Если Новый Файл("response.txt").Существует() Тогда
КопироватьФайл("response.txt", Путь);
КонецЕсли;
КонецПроцедуры

'''
harness += source[start:end]
harness += '''
Лог = Логирование.ПолучитьЛог("test.incremental");
мИсключениеПриОшибкеВыполненияКоманды = АргументыКоманднойСтроки[1] = "raise";
Результат = ПроверитьВозможностьОбновленияФайловВыгрузки(ТекущийКаталог(), АргументыКоманднойСтроки[0], "", АргументыКоманднойСтроки[2] = "allow");
Сообщить(?(Результат, "INCREMENTAL", "FULL"));
'''
script = root / 'check.os'
script.write_text(harness, encoding='utf-8-sig')
env = os.environ.copy()
env.pop('OSLIB_LOADER_DUPLICATES', None)
result = subprocess.run(
['oscript', str(script), str(reference) if explicit else '',
'raise' if raise_errors else 'ignore', 'allow' if allow_empty else 'deny'],
cwd=root, env=env, capture_output=True, text=True, timeout=30)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertEqual(result.stdout.strip(), expected)

def test_empty_response(self):
self.check_response(b'', 'INCREMENTAL')

def test_bom_only_response(self):
self.check_response(b'\xef\xbb\xbf', 'INCREMENTAL', explicit=True)

def test_modified(self):
self.check_response(b'Modified:Configuration.Test\r\n', 'INCREMENTAL')

def test_new(self):
self.check_response(b'New:Catalog.Test\r\n', 'INCREMENTAL')

def test_full_dump(self):
self.check_response(b'FullDump\r\n', 'FULL')

def test_full_dump_case_insensitive(self):
self.check_response(b'fulldump\r\n', 'FULL')

def test_missing_response(self):
self.check_response(None, 'FULL')

def test_missing_versions(self):
self.check_response(b'', 'FULL', versions=False)

def test_external_reference_without_local_versions(self):
self.check_response(b'', 'INCREMENTAL', versions=False, explicit=True)

def test_empty_response_with_suppressed_errors_stays_full(self):
self.check_response(b'', 'FULL', raise_errors=False)

def test_empty_response_for_extension_stays_full(self):
self.check_response(b'', 'FULL', allow_empty=False)

def check_command(self, relative_versions, expected_external):
source = SOURCE.read_text(encoding='utf-8-sig')
start = source.index('Процедура ВыгрузитьКонфигурациюВФайлы(')
end = source.index('КонецПроцедуры', start) + len('КонецПроцедуры')
harness = '''Перем РежимВыгрузкиКонфигурации;
Функция СтандартныеПараметрыЗапускаКонфигуратора()
Возврат Новый Массив;
КонецФункции
Функция ОбернутьВКавычки(Значение)
Возврат Значение;
КонецФункции
Функция ИспользуемаяВерсияПлатформыСтаршеИлиРавна(Версия)
Возврат Истина;
КонецФункции
Функция ПроверитьВозможностьОбновленияФайловВыгрузки(Каталог, Версии, Формат, ПустойОтвет)
Возврат Истина;
КонецФункции
Процедура ВыполнитьКоманду(Параметры)
Для Каждого Параметр Из Параметры Цикл
Сообщить(Параметр);
КонецЦикла;
КонецПроцедуры
'''
harness += source[start:end]
harness += '\nВыгрузитьКонфигурациюВФайлы(ТекущийКаталог(), "Hierarchical", Истина, АргументыКоманднойСтроки[0]);\n'
with tempfile.TemporaryDirectory(prefix='v8runner-command-') as directory:
root = Path(directory)
script = root / 'command.os'
script.write_text(harness, encoding='utf-8-sig')
versions = str(root / 'ConfigDumpInfo.xml') if relative_versions is None else relative_versions
result = subprocess.run(['oscript', str(script), versions], cwd=root,
capture_output=True, text=True, timeout=30)
self.assertEqual(result.returncode, 0, result.stdout + result.stderr)
self.assertIn('-update', result.stdout.splitlines())
self.assertEqual('-configDumpInfoForChanges' in result.stdout, expected_external)

def test_same_absolute_versions_update_in_place(self):
self.check_command(None, False)

def test_same_relative_versions_update_in_place(self):
self.check_command('ConfigDumpInfo.xml', False)

def test_external_versions_retained(self):
self.check_command('../reference/ConfigDumpInfo.xml', True)

def test_implicit_versions_update_in_place(self):
self.check_command('', False)


if __name__ == '__main__':
unittest.main()