#!/usr/bin/env dart
// Copyright (c) 2015, 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.

library readonly_message_test;

import 'package:test/test.dart';

import 'package:protobuf/protobuf.dart'
    show
        BuilderInfo,
        GeneratedMessage,
        PbFieldType,
        UnknownFieldSetField,
        frozenMessageModificationHandler,
        defaultFrozenMessageModificationHandler;

throwsError(Type expectedType, Matcher expectedMessage) =>
    throwsA(predicate((x) {
      expect(x.runtimeType, expectedType);
      expect(x.message, expectedMessage);
      return true;
    }));

class Rec extends GeneratedMessage {
  static Rec getDefault() => new Rec()..freeze();
  static Rec create() => new Rec();

  @override
  BuilderInfo info_ = new BuilderInfo('rec')
    ..a(1, 'value', PbFieldType.O3)
    ..pp<Rec>(2, 'sub', PbFieldType.PM, (_) {}, Rec.create)
    ..p<int>(10, 'ints', PbFieldType.P3);

  int get value => $_get(0, 0);
  set value(int v) {
    $_setUnsignedInt32(0, v);
  }

  bool hasValue() => $_has(0);

  List<Rec> get sub => $_getList<Rec>(1);

  List<int> get ints => $_getList<int>(2);

  @override
  Rec clone() => new Rec()..mergeFromMessage(this);

  Rec copyWith(void Function(Rec) updates) =>
      super.copyWith((message) => updates(message as Rec));
}

main() {
  test('can write a read-only message', () {
    expect(Rec.getDefault().writeToBuffer(), []);
    expect(Rec.getDefault().writeToJson(), "{}");
  });

  test("can't merge to a read-only message", () {
    expect(
        () => Rec.getDefault().mergeFromJson('{"1":1}'),
        throwsError(UnsupportedError,
            equals('Attempted to change a read-only message (rec)')));
  });

  test("can't set a field on a read-only message", () {
    expect(
        () => Rec.getDefault().setField(1, 456),
        throwsError(UnsupportedError,
            equals('Attempted to change a read-only message (rec)')));
  });

  test('can set a field on a read-only message with a custom read-only handler',
      () {
    try {
      int called = 0;

      frozenMessageModificationHandler =
          (String messageName, [String methodName]) {
        expect(messageName, 'rec');
        expect(methodName, isNull);
        called++;
      };

      Rec.getDefault().setField(1, 456);
      expect(called, 1);
    } finally {
      frozenMessageModificationHandler =
          defaultFrozenMessageModificationHandler;
    }
  });

  test("can't clear a read-only message", () {
    expect(
        () => Rec.getDefault().clear(),
        throwsError(UnsupportedError,
            equals('Attempted to change a read-only message (rec)')));
  });

  test("can't clear a field on a read-only message", () {
    expect(
        () => Rec.getDefault().clearField(1),
        throwsError(UnsupportedError,
            equals('Attempted to change a read-only message (rec)')));
  });

  test("can't modify repeated fields on a read-only message", () {
    expect(() => Rec.getDefault().sub.add(Rec.create()),
        throwsError(UnsupportedError, contains('add')));
    var r = Rec.create()
      ..ints.add(10)
      ..freeze();
    expect(
        () => r.ints.clear(),
        throwsError(UnsupportedError,
            equals('Cannot call clear on an unmodifiable list')));
    expect(
        () => r.ints[0] = 2,
        throwsError(UnsupportedError,
            equals('Cannot call set on an unmodifiable list')));
    expect(() => r.sub.add(Rec.create()),
        throwsError(UnsupportedError, contains('add')));

    r = Rec.create()
      ..sub.add(Rec.create())
      ..freeze();
    expect(
        () => r.sub.add(Rec.create()),
        throwsError(UnsupportedError,
            equals('Cannot call add on an unmodifiable list')));
    expect(() => r.ints.length = 20,
        throwsError(UnsupportedError, contains('length')));
  });

  test("can't modify sub-messages on a read-only message", () {
    var subMessage = Rec.create()..value = 1;
    var r = Rec.create()
      ..sub.add(Rec.create()..sub.add(subMessage))
      ..freeze();
    expect(r.sub[0].sub[0].value, 1);
    expect(
        () => subMessage.value = 2,
        throwsError(UnsupportedError,
            equals('Attempted to change a read-only message (rec)')));
  });

  test("can't modify unknown fields on a read-only message", () {
    expect(
        () => Rec.getDefault().unknownFields.clear(),
        throwsError(
            UnsupportedError,
            equals(
                "Attempted to call clear on a read-only message (UnknownFieldSet)")));
  });

  test("can rebuild a frozen message with merge", () {
    final orig = Rec.create()
      ..value = 10
      ..freeze();
    final rebuilt = orig.copyWith((m) => m.mergeFromJson('{"1": 7}'));
    expect(identical(orig, rebuilt), false);
    expect(orig.value, 10);
    expect(rebuilt.value, 7);
  });

  test("can set a field while rebuilding a frozen message", () {
    final orig = Rec.create()
      ..value = 10
      ..freeze();
    final rebuilt = orig.copyWith((m) => m.value = 7);
    expect(identical(orig, rebuilt), false);
    expect(orig.value, 10);
    expect(rebuilt.value, 7);
  });

  test("can clear while rebuilding a frozen message", () {
    final orig = Rec.create()
      ..value = 10
      ..freeze();
    final rebuilt = orig.copyWith((m) => m.clear());
    expect(identical(orig, rebuilt), false);
    expect(orig.value, 10);
    expect(orig.hasValue(), true);
    expect(rebuilt.hasValue(), false);
  });

  test("can clear a field while rebuilding a frozen message", () {
    final orig = Rec.create()
      ..value = 10
      ..freeze();
    final rebuilt = orig.copyWith((m) => m.clearField(1));
    expect(identical(orig, rebuilt), false);
    expect(orig.value, 10);
    expect(orig.hasValue(), true);
    expect(rebuilt.hasValue(), false);
  });

  test("can modify repeated fields while rebuilding a frozen message", () {
    var orig = Rec.create()
      ..ints.add(10)
      ..freeze();
    var rebuilt = orig.copyWith((m) => m.ints.add(12));
    expect(identical(orig, rebuilt), false);
    expect(orig.ints, [10]);
    expect(rebuilt.ints, [10, 12]);

    rebuilt = orig.copyWith((m) => m.ints.clear());
    expect(orig.ints, [10]);
    expect(rebuilt.ints, []);

    rebuilt = orig.copyWith((m) => m.ints[0] = 2);
    expect(orig.ints, [10]);
    expect(rebuilt.ints, [2]);

    orig = Rec.create()
      ..sub.add(Rec.create())
      ..freeze();
    rebuilt = orig.copyWith((m) => m.sub.add(Rec.create()));
    expect(orig.sub.length, 1);
    expect(rebuilt.sub.length, 2);
  });

  test("can modify sub-messages while rebuilding a frozen message", () {
    final subMessage = Rec.create()..value = 1;
    final orig = Rec.create()
      ..sub.add(Rec.create()..sub.add(subMessage))
      ..freeze();

    final rebuilt = orig.copyWith((m) {
      expect(
          () => subMessage.value = 5,
          throwsError(UnsupportedError,
              equals('Attempted to change a read-only message (rec)')));
      m.sub[0].sub[0].value = 2;
    });
    expect(identical(subMessage, orig.sub[0].sub[0]), true);
    expect(identical(subMessage, rebuilt.sub[0].sub[0]), false);
    expect(orig.sub[0].sub[0].value, 1);
    expect(rebuilt.sub[0].sub[0].value, 2);
  });

  test("can modify unknown fields while rebuilding a frozen message", () {
    final orig = Rec.create()
      ..unknownFields.addField(20, new UnknownFieldSetField()..fixed32s.add(1));
    final rebuilt = orig.copyWith((m) => m.unknownFields.clear());
    expect(orig.unknownFields.hasField(20), true);
    expect(rebuilt.unknownFields.hasField(20), false);
  });
}
