diff --git a/src/OneScript.StandardLibrary/Binary/GenericStream.cs b/src/OneScript.StandardLibrary/Binary/GenericStream.cs index 0abc2f232..5c00d611c 100644 --- a/src/OneScript.StandardLibrary/Binary/GenericStream.cs +++ b/src/OneScript.StandardLibrary/Binary/GenericStream.cs @@ -8,6 +8,7 @@ This Source Code Form is subject to the terms of the using System; using System.IO; using OneScript.Contexts; +using OneScript.Exceptions; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -135,6 +136,8 @@ public void Close() [ContextMethod("Записать", "Write")] public void Write(BinaryDataBuffer buffer, int positionInBuffer, int number) { + if (!CanWrite) + throw new RuntimeException("Попытка записи в поток не поддерживающий запись", "Cannot write to a stream that does not support writing"); _commonImpl.Write(buffer, positionInBuffer, number); } @@ -271,6 +274,8 @@ public long CurrentPosition() [ContextMethod("УстановитьРазмер", "SetSize")] public void SetSize(long size) { + if (!CanWrite) + throw new RuntimeException("Попытка записи в поток не поддерживающий запись", "Cannot write to a stream that does not support writing"); _commonImpl.SetSize(size); } diff --git a/tests/binary-objects.os b/tests/binary-objects.os index 631c39f21..f5db51764 100644 --- a/tests/binary-objects.os +++ b/tests/binary-objects.os @@ -29,6 +29,8 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоПриЗаписиВБуферСНевернымИндексомВыбрасываетсяИсключение"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоКорректноРаботаютПобитовыеОперацииЗаписиВБуферДвоичныхДанных"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМетодОткрытьПотокДляЧтенияВозвращаетПотокТолькоДляЧтения"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоПолучитьПотокТолькоДляЧтенияЗапрещаетЗапись"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоПолучитьПотокТолькоДляЧтенияРазделяетДанныеИПозицию"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоХешированиеРаботаетСПотоком"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоХешированиеРаботаетСДвоичнымиДанными"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоПрочитатьБайтНеВыбрасываетИсключениеВКонцеПотока"); @@ -325,6 +327,112 @@ КонецПроцедуры +Процедура ТестДолжен_ПроверитьЧтоПолучитьПотокТолькоДляЧтенияЗапрещаетЗапись() Экспорт + + Поток = Новый ПотокВПамяти(); + Буфер = Новый БуферДвоичныхДанных(10); + Поток.Записать(Буфер, 0, 10); // Запишем какие-то данные + + // Получим поток только для чтения + ПотокДляЧтения = Поток.ПолучитьПотокТолькоДляЧтения(); + + // Проверим, что поток помечен как read-only + юТест.ПроверитьЛожь(ПотокДляЧтения.ДоступнаЗапись); + + // Попытаемся записать в поток только для чтения - должно выбросить исключение + Попытка + ПотокДляЧтения.Записать(Новый БуферДвоичныхДанных(10), 0, 10); + ВызватьИсключение "Ожидали исключение при записи в поток только для чтения, но его не было"; + Исключение + ОписаниеОшибки = ИнформацияОбОшибке().Описание; + юТест.ПроверитьВхождение(ОписаниеОшибки, "Попытка записи в поток не поддерживающий запись"); + КонецПопытки; + + // Также проверим, что изменение размера тоже запрещено + Попытка + ПотокДляЧтения.УстановитьРазмер(20); + ВызватьИсключение "Ожидали исключение при изменении размера потока только для чтения, но его не было"; + Исключение + ОписаниеОшибки = ИнформацияОбОшибке().Описание; + юТест.ПроверитьВхождение(ОписаниеОшибки, "Попытка записи в поток не поддерживающий запись"); + КонецПопытки; + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьЧтоПолучитьПотокТолькоДляЧтенияРазделяетДанныеИПозицию() Экспорт + + // Создаем поток с данными + Поток = Новый ПотокВПамяти(); + Буфер = Новый БуферДвоичныхДанных(20); + + // Заполним буфер данными + Для Индекс = 0 По 19 Цикл + Буфер.Установить(Индекс, Индекс + 1); + КонецЦикла; + + Поток.Записать(Буфер, 0, 20); + юТест.ПроверитьРавенство(20, Поток.Размер()); + юТест.ПроверитьРавенство(20, Поток.ТекущаяПозиция()); + + // Сбросим позицию на начало + Поток.Перейти(0, ПозицияВПотоке.Начало); + юТест.ПроверитьРавенство(0, Поток.ТекущаяПозиция()); + + // Получим поток только для чтения + ПотокДляЧтения = Поток.ПолучитьПотокТолькоДляЧтения(); + + // Проверим, что начальная позиция общая + юТест.ПроверитьРавенство(0, ПотокДляЧтения.ТекущаяПозиция()); + + // Прочитаем из основного потока 5 байт - позиция должна сдвинуться в обоих потоках + БуферЧтения = Новый БуферДвоичныхДанных(5); + Поток.Прочитать(БуферЧтения, 0, 5); + + // Проверим, что позиция изменилась в обоих потоках + юТест.ПроверитьРавенство(5, Поток.ТекущаяПозиция()); + юТест.ПроверитьРавенство(5, ПотокДляЧтения.ТекущаяПозиция()); + + // Прочитаем из потока только для чтения еще 3 байта + БуферЧтения2 = Новый БуферДвоичныхДанных(3); + ПотокДляЧтения.Прочитать(БуферЧтения2, 0, 3); + + // Проверим, что позиция изменилась в обоих потоках + юТест.ПроверитьРавенство(8, Поток.ТекущаяПозиция()); + юТест.ПроверитьРавенство(8, ПотокДляЧтения.ТекущаяПозиция()); + + // Проверим, что данные одинаковые - прочитали байты с 6-го по 8-й (значения 6, 7, 8) + юТест.ПроверитьРавенство(6, БуферЧтения2.Получить(0)); + юТест.ПроверитьРавенство(7, БуферЧтения2.Получить(1)); + юТест.ПроверитьРавенство(8, БуферЧтения2.Получить(2)); + + // Изменим позицию в потоке только для чтения + ПотокДляЧтения.Перейти(15, ПозицияВПотоке.Начало); + + // Проверим, что позиция изменилась в обоих потоках + юТест.ПроверитьРавенство(15, Поток.ТекущаяПозиция()); + юТест.ПроверитьРавенство(15, ПотокДляЧтения.ТекущаяПозиция()); + + // Запишем данные в основной поток (в позицию 15) + БуферЗаписи = Новый БуферДвоичныхДанных(2); + БуферЗаписи.Установить(0, 100); + БуферЗаписи.Установить(1, 200); + Поток.Записать(БуферЗаписи, 0, 2); + + // Позиция должна сдвинуться в обоих потоках + юТест.ПроверитьРавенство(17, Поток.ТекущаяПозиция()); + юТест.ПроверитьРавенство(17, ПотокДляЧтения.ТекущаяПозиция()); + + // Вернемся к позиции 15 и прочитаем из потока только для чтения + ПотокДляЧтения.Перейти(15, ПозицияВПотоке.Начало); + БуферЧтения3 = Новый БуферДвоичныхДанных(2); + ПотокДляЧтения.Прочитать(БуферЧтения3, 0, 2); + + // Проверим, что мы прочитали измененные данные - данные общие между потоками + юТест.ПроверитьРавенство(100, БуферЧтения3.Получить(0)); + юТест.ПроверитьРавенство(200, БуферЧтения3.Получить(1)); + +КонецПроцедуры + Процедура ТестДолжен_ПроверитьЧтоХешированиеРаботаетСПотоком() Экспорт ДвоичныеДанные = ПолучитьДвоичныеДанныеИзHexСтроки("1b1e c416 6a11 c03b 3afe faea 442e 7709");