//
// Copyright 2024 Formata, Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
test: {
a: 'A',
b: 'B',
#[something]
c: 'C',
fn test_func(): int {
return 42;
}
}
#[test]
fn obj_len() {
assertEq(self.test.len(), 3);
}
#[test]
fn get_at() {
assertEq(self.test.at('a'), 'A');
assertEq(self.test['b'], 'B');
let keys = [];
for (field in self.test) {
keys.push(field[0]);
}
keys.sort();
assertEq(keys, ['a', 'b', 'c']);
}
#[test]
fn create_references() {
let ref_obj = new {};
ref_obj.reference('super.test.c');
assertEq(self.test.c, ref_obj.c);
ref_obj.reference(self, 'test.a');
assertEq(self.test.a, ref_obj.a);
}
#[test]
fn get_fields() {
let fields = self.test.fields();
assertEq(fields.len(), 3);
assertEq(fields.first(), ('a', 'A'));
}
#[test]
fn get_attributes() {
let attrs = self.test.attributes('c');
assertEq(attrs, map([('something', null)]));
}
#[test]
fn get_funcs() {
let funcs = self.test.funcs();
assertEq(funcs.len(), 1);
assertEq(funcs.first().at(0), 'test_func');
}
#[test]
fn get_keys() {
let keys = self.test.keys();
keys.sort();
assertEq(keys, ['a', 'b', 'c']);
}
#[test]
fn get_values() {
let values = self.test.values();
values.sort();
assertEq(values, ['A', 'B', 'C']);
}
set_obj: {
a: 'A'
}
#[test]
fn set_fields() {
assert(self.set_obj.set('a', 'B'));
assert(self.set_obj.set('other.a', 'a'));
assertEq(self.set_obj.a, 'B');
assertEq(self.set_obj.other.a, 'a');
}
#[test]
fn get_name() {
assertEq(self.test.name(), 'test');
}
#[test]
fn get_parent() {
assertNeq(self.test.parent(), null);
}
#[test]
fn get_root() {
assertNeq(self.test.root(), null);
}
#[test]
fn is_root() {
assertNot(self.test.isRoot());
assert(root.isRoot());
}
#[test]
fn get_path() {
let path = self.test.path();
assert(path.len() > 0);
}
#[test]
fn get_children() {
assert(self.children().len() > 0);
}
set_prototype: {
type CustomType {
fn hey(): str { return 'hey'; }
}
CustomType typed: {}
untyped: {
fn dude(): str { return 'dude'; }
}
other: {}
#[test]
fn get_set() {
self.untyped.setPrototype(self.typed.prototype());
assertEq(typename self.untyped, "CustomType");
assertEq(self.untyped.hey(), 'hey');
self.other.setPrototype(self.untyped);
assertEq(self.other.dude(), 'dude');
assertEq(typename self.other, 'obj'); // doesn't have a type name...
self.untyped.typename = 'Hacked';
assertEq(typename self.other, 'Hacked');
}
}
rename_move: {
field: 'test'
blah: 'blah'
sub: {}
inplace: 'still here'
#[test]
fn move_field() {
self.moveField('field', 'sub.field');
assertEq(self.field, null);
assertEq(self.sub.field, 'test');
}
#[test]
fn rename_field() {
self.renameField('blah', 'sub.duh');
assertEq(self.blah, null);
assertEq(self.sub.duh, 'blah');
}
#[test]
fn rename_in_place() {
self.renameField('inplace', 'success');
assertEq(self.inplace, null);
assertEq(self.success, 'still here');
}
}
box_fields: {
value: 42
another: 1
#[test]
fn box_field() {
assert(self.box('value'));
let v = self.value;
v = 100;
assertEq(self.value, 100);
}
#[test]
fn box_set_value() {
assert(self.box('another', 10));
assertEq(self.another, 10);
let v = self.another;
v = 44;
assertEq(self.another, 44);
}
#[test]
fn box_null_value() {
assert(self.box('dude', 'hi'));
assertEq(self.dude, 'hi');
let v = self.dude;
v = 'hello';
assert(isBoxed(self.dude));
assertEq(self.dude, 'hello');
}
}
unbox_fields: {
value: box(32)
#[test]
fn unbox_value() {
let v = self.value;
v = 10;
assertEq(self.value, 10);
assert(self.unbox('value'));
v = 100;
assertEq(self.value, 10);
}
#[test]
fn unbox_set() {
assertNot(self.unbox('dne')); // won't set without a given value...
assert(self.unbox('another', box(20)));
assertEq(self.another, 20);
let v = self.another;
v = 100;
assertEq(self.another, 20);
}
}
remove_fields_funcs: {
some_obj: {}
field: 'field'
fn test_fn() {}
sub: {
field: 'field'
}
#[test]
fn remove_field_obj() {
// this will drop the object as well...
assert(self.removeField('some_obj', true));
assertNull(self.some_obj);
}
#[test]
fn remove_field_path() {
assertEq(self.sub.field, 'field');
assert(self.removeField('sub.field'));
assertNull(self.sub.field);
}
#[test]
fn remove_field() {
assert(self.removeField('field'));
assertNull(self.field);
assertNot(self.removeField('dne'));
}
#[test]
fn remove_func() {
assertNeq(self.test_fn, null);
assert(self.removeFunc('test_fn'));
assertNull(self.test_fn);
}
}
cloned_objects: {
source: {
a: 'a',
b: 'b',
c: 'c',
}
#[test]
fn shallow_copy() {
// Add all of 'source' fields to copy by reference (in two places at once)
let copy = new {};
for (key in self.source.keys()) copy.reference(self.source, key);
assertEq(copy.a, 'a');
assertEq(copy.b, 'b');
assertEq(copy.c, 'c');
assertEq(self.source.a, 'a');
assertEq(self.source.b, 'b');
assertEq(self.source.c, 'c');
self.source.a = 'AA';
assertEq(copy.a, 'AA');
}
source1: {
a: 'a',
b: 'b',
c: 'c',
sub: {
a: 'a',
}
}
#[test]
fn shallow_copy_helper() {
// does the same thing as the 'shallow_copy' test, but gets functions and all other data too...
let copy = new {};
copy.shallowCopy(self.source1);
assertEq(copy.a, 'a');
assertEq(copy.b, 'b');
assertEq(copy.c, 'c');
assertEq(copy.sub.a, 'a');
assertEq(self.source1.a, 'a');
assertEq(self.source1.b, 'b');
assertEq(self.source1.c, 'c');
assertEq(self.source1.sub.a, 'a');
self.source1.a = 'AA';
assertEq(copy.a, 'AA');
self.source1.sub.a = 'AA';
assertEq(copy.sub.a, 'AA');
}
source2: {
a: 'a',
b: 'b',
c: 'c',
sub: {
a: 'a',
}
}
#[test]
fn deep_copy() {
let copy = new {};
copy.deepCopyFields(self.source2);
assertEq(copy.a, 'a');
assertEq(copy.b, 'b');
assertEq(copy.c, 'c');
assertEq(copy.sub.a, 'a');
assertEq(self.source2.a, 'a');
assertEq(self.source2.b, 'b');
assertEq(self.source2.c, 'c');
assertEq(self.source2.sub.a, 'a');
self.source2.a = 'AA';
assertEq(copy.a, 'a');
self.source2.sub.a = 'AA';
assertEq(copy.sub.a, 'a');
}
}
map_fields: {
source: {
a: 'a',
b: 'b',
c: 'c',
d: 'd',
e: 'e',
}
dest: {
E: 'HERE',
}
#[test]
fn source_to_dest() {
let mapping = map([
// (source path, destination path)
('source.a', 'dest.A'),
('source.b', 'dest.B'),
('source.c', 'dest.C'),
('source.d', 'dest.D'),
('source.e', 'dest.E'),
]);
let successes = self.mapFields(mapping);
assertEq(successes, mapping); // all mappings succeeded
assertEq(self.dest.A, 'a');
assertEq(self.dest.B, 'b');
assertEq(self.dest.C, 'c');
assertEq(self.dest.D, 'd');
assertEq(self.dest.E, ['HERE', 'e']);
assertNull(self.source.a);
assertNull(self.source.b);
assertNull(self.source.c);
assertNull(self.source.d);
assertNull(self.source.e);
}
}
search: {
a: 'ASearch'
b: 'BSearch'
h: {
i: {
g: 'G'
j: {
k: {
eq: 'EQUP'
}
}
}
}
space: {
a: 'ASpace'
sub: {
a: 'ASub'
b: 'BSub'
c: {
d: {
e: {
f: {
g: 'GD'
eq: 'EQDOWN'
}
}
}
}
}
}
#[test]
fn searchUp() {
let val = self.space.searchUp('a');
assertEq(val[0], 'ASpace');
assertEq(val[1], 0);
val = self.space.searchUp('a', true, [self.space]);
assertEq(val[0], 'ASearch');
assertEq(val[1], 1);
val = self.space.searchUp('b');
assertEq(val[0], 'BSearch');
assertEq(val[1], 1);
val = self.space.searchUp('search_dne');
assertNull(val);
val = self.space.searchUp('g');
assertEq(val[0], 'G');
assertEq(val[1], 3);
val = self.space.searchUp('g', false);
assertNull(val);
}
#[test]
fn searchDown() {
let val = self.space.searchDown('a');
assertEq(val[0], 'ASpace');
assertEq(val[1], 0);
val = self.space.searchDown('a', 0, [self.space]);
assertEq(val[0], 'ASub');
assertEq(val[1], 1);
val = self.space.searchDown('b');
assertEq(val[0], 'BSub');
assertEq(val[1], 1);
val = self.space.searchDown('search_dne');
assertNull(val);
val = self.space.searchDown('g');
assertEq(val[0], 'GD');
assertEq(val[1], 5);
}
#[test]
fn search() {
let val = self.space.search('a');
assertEq(val[0], 'ASpace');
assertEq(val[1], 0);
val = self.space.search('a', true, [self.space]);
assertEq(val[0], 'ASub');
assertEq(val[1], 1);
val = self.space.search('b');
assertEq(val[0], 'BSub'); // down is prioritized
assertEq(val[1], 1);
val = self.space.search('g');
assertEq(val[0], 'G');
assertEq(val[1], 3);
val = self.space.search('g', false);
assertEq(val[0], 'GD');
assertEq(val[1], 5);
val = self.space.search('eq');
assertEq(val[0], 'EQDOWN'); // down is preferred
assertEq(val[1], 5);
val = self.space.searchUp('eq');
assertEq(val[0], 'EQUP');
assertEq(val[1], 5); // make sure testing the right thing above
}
}