//
// 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(['hi'])]
fn push(): vec {
let array = [];
array.push('hi');
return array;
}
#[test]
fn append() {
let a = [1, 2, 3, 4, 5];
let b = [6, 7, 8, 9];
a.append(b);
assertEq(a, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
assertEq(b, [6, 7, 8, 9]);
}
#[test]
fn append_boxed() {
let a = [1, 2, 3, 4, 5];
let b = box([6, 7, 8, 9]);
a.append(b);
assertEq(a, [1, 2, 3, 4, 5, 6, 7, 8, 9]);
assertEq(b, []);
}
#[test(['hi'])]
fn pop(): vec {
let array = ['hi', 'there'];
assertEq(array.pop(), 'there');
return array;
}
#[test([1, 2, 4, 5, 6])]
fn pop_at(): vec {
let array = [1, 2, 3, 4, 5, 6];
assertEq(array.pop(2), 3); // if given a number param, it is treated as an index
return array;
}
#[test(['a', 'c', 'd', 'e'])]
fn pop_val(): vec {
let array: vec = ['a', 'b', 'c', 'd', 'e'];
assertEq(array.pop('b'), 'b');
return array;
}
#[test]
fn reverse() {
let array = [1, 2, 3, 4];
array.reverse();
assertEq(array, [4, 3, 2, 1]);
}
#[test]
fn reversed() {
let array = [1, 2, 3, 4];
let reversed = array.reversed();
assertEq(array, [1, 2, 3, 4]);
assertEq(reversed, [4, 3, 2, 1]);
}
#[test]
fn len() {
let array = [1, 2, 3, 4, 5, 6, 7, 8];
assertEq(array.len(), 8);
}
#[test]
fn empty() {
let array = [];
assert(array.empty());
array.push(1);
assertNot(array.empty());
}
#[test]
fn any() {
let array = [];
assertNot(array.any());
array.push(1);
assert(array.any());
}
#[test]
fn at() {
let array = [1, 2, 3, 4];
assertEq(array.at(2), 3);
assertEq(array[3], 4);
}
#[test]
fn nested_at() {
let array = [[1, 2, 3], [4, 5, 6]];
assertEq(array[0][1], 2);
assertEq(array.at(1).at(2), 6);
}
#[test(1)]
fn first(): int {
let array = [1, 2, 3];
return array.first();
}
#[test(3)]
fn last(): int {
let array = [1, 2, 3];
return array.last();
}
#[test('hello, world')]
fn join(): str {
return ['hello', 'world'].join(', ');
}
#[test]
fn has() {
let array = ['hello', 'world'];
assert(array.has('hello'));
assertNot(array.has('dne'));
assert(array.contains('hello'));
assertNot(array.contains('dne'));
}
#[test]
fn find() {
let array = ['hello', 'world', 5];
assertEq(array.find(5), 2);
assertEq(array.find('world'), 1);
assertEq(array.find('dne'), -1);
assertEq(array.find(2), -1);
}
#[test]
fn remove_first_occurence() {
let array = ['hello', 'world', 5, 4, 'world'];
assertEq(array.remove('dne'), null);
assertEq(array.remove(5), 5);
assertEq(array.remove('world'), 'world');
assertEq(array, ['hello', 4, 'world']);
}
#[test]
fn remove_last_occurence() {
let array = ['hello', 'world', 4, 'world'];
assertEq(array.removeLast('world'), 'world');
assertEq(array, ['hello', 'world', 4]);
}
#[test]
fn remove_all() {
let array = [1, 1, 1, 1, 2, 1, 1, 1, 1];
assertEq(array.removeAll(1).len(), 8);
assertEq(array, [2]);
assert(array.removeAll(1).empty());
}
#[test]
fn insert() {
let array = [1, 2, 3, 4, 5, 6];
array.insert(2, 'hello');
assertEq(array, [1, 2, 'hello', 3, 4, 5, 6]);
}
#[test]
fn set() {
let array = [1, 2, 3, 4, 5, 6];
array.set(2, 'hello');
assertEq(array, [1, 2, 'hello', 4, 5, 6]);
array.replace(4, 42);
assertEq(array, [1, 2, 'hello', 4, 42, 6]);
}
#[test]
fn iter() {
let array = 0..15;
array.iter((val: int): int => {
if (val % 2 == 0) {
return val + 1;
}
return null; // don't set anything
});
assertEq(array, [1, 1, 3, 3, 5, 5, 7, 7, 9, 9, 11, 11, 13, 13, 15]);
}
#[test]
fn retain_numbers() {
let array = [1, 2, 3, 4, 'hi', 9, 'dude', true, {}, 23];
array.retain((val: int): bool => true); // only callable for numbers
assertEq(array, [1, 2, 3, 4, 9, true, 23]); // booleans can cast to numbers
}
#[test]
fn retain_evens() {
let array = 0..100;
array.retain((v: int): int => v % 2 == 0);
assertEq(array, 0..100|2);
}
#[test([0, 1, 2, 2, 4, 5, 5, 7, 8])]
fn sort(): vec {
let array = [5, 2, 4, 5, 7, 8, 0, 2, 1];
array.sort();
return array;
}
#[test([2, 3, 5, 6, 6])]
fn sort_by(): vec {
let array = [new {k:6}, new {k:3}, new {k:5}, new {k:2}, new {k:6}];
array.sort((a: obj, b: obj): int => {
if (a.k < b.k) return -1;
if (a.k > b.k) return 1;
return 0;
});
let res = [];
for (object in array) {
res.push(object.k);
}
return res;
}
boxed_values: {
#[test([2, 3, 4, 4, 'hi', true, 33])]
fn boxed_array(): vec {
let array = box([1, 1, 2, 3, 4, 4]);
assertEq(array.removeAll(1), [1, 1]);
array.push('hi', true, 33);
return array;
}
#[test]
fn boxed_array_value() {
let array = [1, box(42)];
// Mutate the value by reference
{
let val = array.at(1);
assertEq(val, 42);
val += 10;
assertEq(val, 52);
}
{
let val = array.at(1);
assertEq(val, 52);
}
// Unbox the value with helper
{
let val = unbox(array.at(1));
val += 10;
assertEq(val, 62);
}
{
let val = array.at(1);
assertEq(val, 52);
}
// Unbox the value with a cast
{
let val = array.at(1) as int; // unboxed via cast
val += 10;
assertEq(val, 62);
}
{
let val = array.at(1);
assertEq(val, 52);
}
// Push a boxed value by cast
array.push(11 as Box<float>);
let val = array.at(2);
val += 10;
assertEq(val, 21);
assertEq(array.at(2), 21);
}
}