blob: f2b770fe6b0921693c4b1d92650fb1fb4460d434 [file] [log] [blame]
// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:convert';
import 'package:fixnum/fixnum.dart' show Int64;
import 'package:protobuf/protobuf.dart';
import 'package:test/test.dart';
import '../out/protos/foo.pb.dart';
import '../out/protos/google/protobuf/unittest.pb.dart';
void main() {
group('frozen and tobuilder', () {
final original = Outer()
..inner = (Inner()..value = 'foo')
..inners.add(Inner()..value = 'repeatedInner')
..setExtension(FooExt.inner, Inner()..value = 'extension')
..getExtension(FooExt.inners).add(Inner()..value = 'repeatedExtension')
..freeze();
test('can read extensions', () {
expect(original.getExtension(FooExt.inner).value, 'extension');
expect(
original.getExtension(FooExt.inners)[0].value, 'repeatedExtension');
});
test('frozen message cannot be modified', () {
expect(() => original.inner = (Inner()..value = 'bar'),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => original.inner..value = 'bar',
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => original.inners.add(Inner()..value = 'bar'),
throwsA(TypeMatcher<UnsupportedError>()));
});
test('extensions cannot be modified', () {
expect(() => original.setExtension(FooExt.inner, Inner()..value = 'bar'),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => original.getExtension(FooExt.inner).value = 'bar',
throwsA(TypeMatcher<UnsupportedError>()));
expect(
() =>
original.getExtension(FooExt.inners).add(Inner()..value = 'bar'),
throwsA(TypeMatcher<UnsupportedError>()));
});
final builder = original.toBuilder() as Outer;
test('builder is a shallow copy', () {
expect(builder.inner, same(original.inner));
});
test('builder extensions are also copied shallowly', () {
expect(builder.getExtension(FooExt.inner),
same(original.getExtension(FooExt.inner)));
});
test('repeated fields are cloned', () {
expect(builder.inners, isNot(same(original.inners)));
expect(builder.inners[0], same(original.inners[0]));
});
test('repeated extensions are cloned', () {
expect(builder.getExtension(FooExt.inners),
isNot(same(original.getExtension(FooExt.inners))));
expect(builder.getExtension(FooExt.inners)[0],
same(original.getExtension(FooExt.inners)[0]));
});
test(
'the builder is only a shallow copy, the nested message is still frozen.',
() {
expect(() => builder.inner.value = 'bar',
throwsA(TypeMatcher<UnsupportedError>()));
});
test('the builder is mutable', () {
builder.inner = (Inner()..value = 'zop');
expect(builder.inner.value, 'zop');
builder.inners.add(Inner()..value = 'bob');
expect(builder.inners.length, 2);
builder.setExtension(FooExt.inner, Inner()..value = 'nob');
expect(builder.getExtension(FooExt.inner).value, 'nob');
builder.getExtension(FooExt.inners).add(Inner()..value = 'rob');
expect(builder.getExtension(FooExt.inners).length, 2);
});
test('newly created `Inner` is mutable', () {
builder.inner.value = 'bar';
expect(builder.inner.value, 'bar');
});
});
group('map properties behave correctly', () {
late OuterWithMap original;
late OuterWithMap outerBuilder;
setUp(() {
original = OuterWithMap()
..innerMap[1] = (Inner()..value = 'mapInner')
..freeze();
outerBuilder = original.toBuilder() as OuterWithMap;
});
test('map fields are cloned', () {
expect(outerBuilder.innerMap, isNot(same(original.innerMap)));
expect(outerBuilder.innerMap[1], same(original.innerMap[1]));
});
test('the builder is mutable', () {
outerBuilder.innerMap[1] = (Inner()..value = 'mob');
expect(outerBuilder.innerMap[1]!.value, 'mob');
});
});
group('frozen unknown fields', () {
late Inner inner;
late TestEmptyMessage emptyMessage;
late int tagNumber;
late UnknownFieldSet unknownFieldSet;
late UnknownFieldSetField field;
setUp(() {
inner = Inner()..value = 'bob';
emptyMessage = TestEmptyMessage.fromBuffer(inner.writeToBuffer());
tagNumber = inner.getTagNumber('value')!;
unknownFieldSet = emptyMessage.unknownFields;
field = unknownFieldSet.getField(tagNumber)!;
});
test('can read from a frozen unknown fieldset', () {
expect(unknownFieldSet.hasField(tagNumber), isTrue);
expect(field.lengthDelimited[0], utf8.encode(inner.value));
emptyMessage.freeze();
unknownFieldSet = emptyMessage.unknownFields;
field = unknownFieldSet.getField(tagNumber)!;
expect(unknownFieldSet.hasField(tagNumber), isTrue);
expect(field.lengthDelimited[0], utf8.encode(inner.value));
});
test('can add fields to a builder with unknown fields', () {
emptyMessage.freeze();
final builder = emptyMessage.toBuilder() as TestEmptyMessage;
builder.unknownFields
.addField(2, UnknownFieldSetField()..fixed32s.add(42));
expect(builder.unknownFields.getField(2)!.fixed32s[0], 42);
});
test('cannot mutate already added UnknownFieldSetField on builder', () {
emptyMessage.freeze();
final builder = emptyMessage.toBuilder() as TestEmptyMessage;
expect(
() => builder.unknownFields.getField(1)!.lengthDelimited[0] =
utf8.encode('alice'),
throwsA(TypeMatcher<UnsupportedError>()));
});
test('cannot add to a frozen UnknownFieldSetField', () {
emptyMessage.freeze();
expect(
() => field.addFixed32(1), throwsA(TypeMatcher<UnsupportedError>()));
expect(() => field.fixed32s.add(1),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => field.addFixed64(Int64(1)),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => field.fixed64s.add(Int64(1)),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => field.addLengthDelimited([1]),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => field.lengthDelimited.add([1]),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => field.addGroup(unknownFieldSet.clone()),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => field.groups.add(unknownFieldSet.clone()),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => field.addVarint(Int64(1)),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => field.varints.add(Int64(1)),
throwsA(TypeMatcher<UnsupportedError>()));
});
test('cannot add or merge field to a frozen UnknownFieldSet', () {
emptyMessage.freeze();
expect(() => unknownFieldSet.addField(2, field),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => unknownFieldSet.mergeField(2, field),
throwsA(TypeMatcher<UnsupportedError>()));
});
test('cannot merge message into a frozen UnknownFieldSet', () {
emptyMessage.freeze();
final other = emptyMessage.deepCopy();
expect(() => emptyMessage.mergeFromBuffer(other.writeToBuffer()),
throwsA(TypeMatcher<UnsupportedError>()));
expect(() => emptyMessage.mergeFromMessage(other),
throwsA(TypeMatcher<UnsupportedError>()));
});
test('cannot add a field to a frozen UnknownFieldSet', () {
emptyMessage.freeze();
expect(() => unknownFieldSet.addField(tagNumber, field),
throwsA(TypeMatcher<UnsupportedError>()));
});
});
}