blob: 61547876cee1abaf377d94cdceb842ae91884ea6 [file] [log] [blame]
// Copyright (c) 2014, 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 gcloud.db.properties_test;
import 'dart:typed_data';
import 'package:gcloud/datastore.dart' as datastore;
import 'package:gcloud/db.dart';
import 'package:test/test.dart';
void main() {
group('properties', () {
var datastoreKey = datastore.Key([datastore.KeyElement('MyKind', 42)],
partition: datastore.Partition('foonamespace'));
var dbKey = KeyMock(datastoreKey);
var modelDBMock = ModelDBMock(datastoreKey, dbKey);
test('bool_property', () {
var prop = const BoolProperty(required: true);
expect(prop.validate(modelDBMock, null), isFalse);
prop = const BoolProperty(required: false);
expect(prop.validate(modelDBMock, null), isTrue);
expect(prop.validate(modelDBMock, true), isTrue);
expect(prop.validate(modelDBMock, false), isTrue);
expect(prop.encodeValue(modelDBMock, null), equals(null));
expect(prop.encodeValue(modelDBMock, true), equals(true));
expect(prop.encodeValue(modelDBMock, false), equals(false));
expect(prop.decodePrimitiveValue(modelDBMock, null), equals(null));
expect(prop.decodePrimitiveValue(modelDBMock, true), equals(true));
expect(prop.decodePrimitiveValue(modelDBMock, false), equals(false));
});
test('int_property', () {
var prop = const IntProperty(required: true);
expect(prop.validate(modelDBMock, null), isFalse);
prop = const IntProperty(required: false);
expect(prop.validate(modelDBMock, null), isTrue);
expect(prop.validate(modelDBMock, 33), isTrue);
expect(prop.encodeValue(modelDBMock, null), equals(null));
expect(prop.encodeValue(modelDBMock, 42), equals(42));
expect(prop.decodePrimitiveValue(modelDBMock, null), equals(null));
expect(prop.decodePrimitiveValue(modelDBMock, 99), equals(99));
});
test('double_property', () {
var prop = const DoubleProperty(required: true);
expect(prop.validate(modelDBMock, null), isFalse);
prop = const DoubleProperty(required: false);
expect(prop.validate(modelDBMock, null), isTrue);
expect(prop.validate(modelDBMock, 33.0), isTrue);
expect(prop.encodeValue(modelDBMock, null), equals(null));
expect(prop.encodeValue(modelDBMock, 42.3), equals(42.3));
expect(prop.decodePrimitiveValue(modelDBMock, null), equals(null));
expect(prop.decodePrimitiveValue(modelDBMock, 99.1), equals(99.1));
});
test('string_property', () {
var prop = const StringProperty(required: true);
expect(prop.validate(modelDBMock, null), isFalse);
prop = const StringProperty(required: false);
expect(prop.validate(modelDBMock, null), isTrue);
expect(prop.validate(modelDBMock, 'foobar'), isTrue);
expect(prop.encodeValue(modelDBMock, null), equals(null));
expect(prop.encodeValue(modelDBMock, 'foo'), equals('foo'));
expect(prop.decodePrimitiveValue(modelDBMock, null), equals(null));
expect(prop.decodePrimitiveValue(modelDBMock, 'bar'), equals('bar'));
});
test('blob_property', () {
var prop = const BlobProperty(required: true);
expect(prop.validate(modelDBMock, null), isFalse);
prop = const BlobProperty(required: false);
expect(prop.validate(modelDBMock, null), isTrue);
expect(prop.validate(modelDBMock, [1, 2]), isTrue);
expect(prop.encodeValue(modelDBMock, null), equals(null));
expect(
(prop.encodeValue(modelDBMock, <int>[]) as datastore.BlobValue).bytes,
equals([]));
expect(
(prop.encodeValue(modelDBMock, [1, 2]) as datastore.BlobValue).bytes,
equals([1, 2]));
expect(
(prop.encodeValue(modelDBMock, Uint8List.fromList([1, 2]))
as datastore.BlobValue)
.bytes,
equals([1, 2]));
expect(prop.decodePrimitiveValue(modelDBMock, null), equals(null));
expect(prop.decodePrimitiveValue(modelDBMock, datastore.BlobValue([])),
equals([]));
expect(
prop.decodePrimitiveValue(modelDBMock, datastore.BlobValue([5, 6])),
equals([5, 6]));
expect(
prop.decodePrimitiveValue(
modelDBMock, datastore.BlobValue(Uint8List.fromList([5, 6]))),
equals([5, 6]));
});
test('datetime_property', () {
var utc99 = DateTime.fromMillisecondsSinceEpoch(99, isUtc: true);
var prop = const DateTimeProperty(required: true);
expect(prop.validate(modelDBMock, null), isFalse);
prop = const DateTimeProperty(required: false);
expect(prop.validate(modelDBMock, null), isTrue);
expect(prop.validate(modelDBMock, utc99), isTrue);
expect(prop.encodeValue(modelDBMock, null), equals(null));
expect(prop.encodeValue(modelDBMock, utc99), equals(utc99));
expect(prop.decodePrimitiveValue(modelDBMock, null), equals(null));
expect(prop.decodePrimitiveValue(modelDBMock, 99 * 1000), equals(utc99));
expect(
prop.decodePrimitiveValue(modelDBMock, 99 * 1000 + 1), equals(utc99));
expect(prop.decodePrimitiveValue(modelDBMock, utc99), equals(utc99));
});
test('list_property', () {
var prop = const ListProperty(BoolProperty());
expect(prop.validate(modelDBMock, null), isFalse);
expect(prop.validate(modelDBMock, []), isTrue);
expect(prop.validate(modelDBMock, [true]), isTrue);
expect(prop.validate(modelDBMock, [true, false]), isTrue);
expect(prop.validate(modelDBMock, [true, false, 1]), isFalse);
expect(prop.encodeValue(modelDBMock, []), equals(null));
expect(prop.encodeValue(modelDBMock, [true]), equals(true));
expect(
prop.encodeValue(modelDBMock, [true, false]), equals([true, false]));
expect(prop.encodeValue(modelDBMock, true, forComparison: true),
equals(true));
expect(prop.encodeValue(modelDBMock, false, forComparison: true),
equals(false));
expect(prop.encodeValue(modelDBMock, null, forComparison: true),
equals(null));
expect(prop.decodePrimitiveValue(modelDBMock, null), equals([]));
expect(prop.decodePrimitiveValue(modelDBMock, []), equals([]));
expect(prop.decodePrimitiveValue(modelDBMock, true), equals([true]));
expect(prop.decodePrimitiveValue(modelDBMock, [true, false]),
equals([true, false]));
});
test('composed_list_property', () {
var prop = const ListProperty(CustomProperty());
var c1 = Custom()..customValue = 'c1';
var c2 = Custom()..customValue = 'c2';
expect(prop.validate(modelDBMock, null), isFalse);
expect(prop.validate(modelDBMock, []), isTrue);
expect(prop.validate(modelDBMock, [c1]), isTrue);
expect(prop.validate(modelDBMock, [c1, c2]), isTrue);
expect(prop.validate(modelDBMock, [c1, c2, 1]), isFalse);
expect(prop.encodeValue(modelDBMock, []), equals(null));
expect(prop.encodeValue(modelDBMock, [c1]), equals(c1.customValue));
expect(prop.encodeValue(modelDBMock, [c1, c2]),
equals([c1.customValue, c2.customValue]));
expect(prop.decodePrimitiveValue(modelDBMock, null), equals([]));
expect(prop.decodePrimitiveValue(modelDBMock, []), equals([]));
expect(
prop.decodePrimitiveValue(modelDBMock, c1.customValue), equals([c1]));
expect(
prop.decodePrimitiveValue(
modelDBMock, [c1.customValue, c2.customValue]),
equals([c1, c2]));
});
test('modelkey_property', () {
var prop = const ModelKeyProperty(required: true);
expect(prop.validate(modelDBMock, null), isFalse);
prop = const ModelKeyProperty(required: false);
expect(prop.validate(modelDBMock, null), isTrue);
expect(prop.validate(modelDBMock, dbKey), isTrue);
expect(prop.validate(modelDBMock, datastoreKey), isFalse);
expect(prop.encodeValue(modelDBMock, null), equals(null));
expect(prop.encodeValue(modelDBMock, dbKey), equals(datastoreKey));
expect(prop.decodePrimitiveValue(modelDBMock, null), equals(null));
expect(
prop.decodePrimitiveValue(modelDBMock, datastoreKey), equals(dbKey));
});
});
}
class Custom {
String? customValue;
@override
int get hashCode => customValue.hashCode;
@override
bool operator ==(other) {
return other is Custom && other.customValue == customValue;
}
}
class CustomProperty extends StringProperty {
const CustomProperty(
{String? propertyName, bool required = false, bool indexed = true});
@override
bool validate(ModelDB db, Object? value) {
if (required && value == null) return false;
return value == null || value is Custom;
}
@override
Object? decodePrimitiveValue(ModelDB db, Object? value) {
if (value == null) return null;
return Custom()..customValue = value as String;
}
@override
Object? encodeValue(ModelDB db, Object? value, {bool forComparison = false}) {
if (value == null) return null;
return (value as Custom).customValue;
}
}
class KeyMock implements Key {
final datastore.Key _datastoreKey;
KeyMock(this._datastoreKey);
@override
Object id = 1;
@override
Type? type;
@override
Key get parent => this;
@override
bool get isEmpty => false;
@override
Partition get partition => throw UnimplementedError('not mocked');
datastore.Key get datastoreKey => _datastoreKey;
@override
Key<T> append<T>(Type modelType, {T? id}) =>
throw UnimplementedError('not mocked');
@override
Key<U> cast<U>() => Key<U>(parent, type, id as U);
@override
// ignore: hash_and_equals
int get hashCode => 1;
}
class ModelDBMock implements ModelDB {
final datastore.Key _datastoreKey;
final Key _dbKey;
ModelDBMock(this._datastoreKey, this._dbKey);
@override
Key fromDatastoreKey(datastore.Key datastoreKey) {
if (!identical(_datastoreKey, datastoreKey)) {
throw 'Broken test';
}
return _dbKey;
}
@override
datastore.Key toDatastoreKey(Key key) {
if (!identical(_dbKey, key)) {
throw 'Broken test';
}
return _datastoreKey;
}
Map<String, Property>? propertiesForModel(modelDescription) => null;
@override
T? fromDatastoreEntity<T extends Model>(datastore.Entity? entity) => null;
@override
datastore.Entity toDatastoreEntity(Model model) =>
throw UnimplementedError('not mocked');
@override
String? fieldNameToPropertyName(String kind, String fieldName) => null;
@override
String kindName(Type type) => throw UnimplementedError('not mocked');
@override
Object? toDatastoreValue(String kind, String fieldName, Object? value,
{bool forComparison = false}) =>
null;
}