libphobos: Generate test files for phobos testsuite
Extracts all public unittests from libphobos/src and emits them as standalone tests in the testsuite using the tests_extractor script. Compiling every module in the Phobos library with unittests included is computationally expensive, and these tests are now only ran when GCC_TEST_RUN_EXPENSIVE is not empty. When instead just compiling the unittests and linking in the module under test, this has been observed to reduce the time spent running the testsuite by more than half. libphobos/ChangeLog: * testsuite/libphobos.phobos/shared/phobos-shared.exp: Require is-effective-target run_expensive_tests. * testsuite/libphobos.phobos/static/phobos-static.exp: Likewise. * testsuite/libphobos.phobos/phobos.exp: New test. * testsuite/libphobos.phobos/std_algorithm_comparison.d: New test. * testsuite/libphobos.phobos/std_algorithm_iteration.d: New test. * testsuite/libphobos.phobos/std_algorithm_mutation.d: New test. * testsuite/libphobos.phobos/std_algorithm_searching.d: New test. * testsuite/libphobos.phobos/std_algorithm_setops.d: New test. * testsuite/libphobos.phobos/std_algorithm_sorting.d: New test. * testsuite/libphobos.phobos/std_array.d: New test. * testsuite/libphobos.phobos/std_ascii.d: New test. * testsuite/libphobos.phobos/std_base64.d: New test. * testsuite/libphobos.phobos/std_bigint.d: New test. * testsuite/libphobos.phobos/std_bitmanip.d: New test. * testsuite/libphobos.phobos/std_checkedint.d: New test. * testsuite/libphobos.phobos/std_complex.d: New test. * testsuite/libphobos.phobos/std_concurrency.d: New test. * testsuite/libphobos.phobos/std_container_array.d: New test. * testsuite/libphobos.phobos/std_container_binaryheap.d: New test. * testsuite/libphobos.phobos/std_container_dlist.d: New test. * testsuite/libphobos.phobos/std_container_rbtree.d: New test. * testsuite/libphobos.phobos/std_container_slist.d: New test. * testsuite/libphobos.phobos/std_container_util.d: New test. * testsuite/libphobos.phobos/std_conv.d: New test. * testsuite/libphobos.phobos/std_csv.d: New test. * testsuite/libphobos.phobos/std_datetime_date.d: New test. * testsuite/libphobos.phobos/std_datetime_interval.d: New test. * testsuite/libphobos.phobos/std_datetime_package.d: New test. * testsuite/libphobos.phobos/std_datetime_stopwatch.d: New test. * testsuite/libphobos.phobos/std_datetime_systime.d: New test. * testsuite/libphobos.phobos/std_datetime_timezone.d: New test. * testsuite/libphobos.phobos/std_demangle.d: New test. * testsuite/libphobos.phobos/std_digest_crc.d: New test. * testsuite/libphobos.phobos/std_digest_hmac.d: New test. * testsuite/libphobos.phobos/std_digest_md.d: New test. * testsuite/libphobos.phobos/std_digest_murmurhash.d: New test. * testsuite/libphobos.phobos/std_digest_package.d: New test. * testsuite/libphobos.phobos/std_digest_ripemd.d: New test. * testsuite/libphobos.phobos/std_digest_sha.d: New test. * testsuite/libphobos.phobos/std_encoding.d: New test. * testsuite/libphobos.phobos/std_exception.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_affix_allocator.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_aligned_block_list.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_allocator_list.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_ascending_page_allocator.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_bitmapped_block.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_bucketizer.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_fallback_allocator.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_free_list.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_kernighan_ritchie.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_quantizer.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_region.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_scoped_allocator.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_segregator.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_building_blocks_stats_collector.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_common.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_gc_allocator.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_mallocator.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_package.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_showcase.d: New test. * testsuite/libphobos.phobos/std_experimental_allocator_typed.d: New test. * testsuite/libphobos.phobos/std_file.d: New test. * testsuite/libphobos.phobos/std_format_package.d: New test. * testsuite/libphobos.phobos/std_format_read.d: New test. * testsuite/libphobos.phobos/std_format_spec.d: New test. * testsuite/libphobos.phobos/std_format_write.d: New test. * testsuite/libphobos.phobos/std_functional.d: New test. * testsuite/libphobos.phobos/std_getopt.d: New test. * testsuite/libphobos.phobos/std_int128.d: New test. * testsuite/libphobos.phobos/std_internal_cstring.d: New test. * testsuite/libphobos.phobos/std_internal_scopebuffer.d: New test. * testsuite/libphobos.phobos/std_json.d: New test. * testsuite/libphobos.phobos/std_logger_core.d: New test. * testsuite/libphobos.phobos/std_logger_nulllogger.d: New test. * testsuite/libphobos.phobos/std_math_algebraic.d: New test. * testsuite/libphobos.phobos/std_math_exponential.d: New test. * testsuite/libphobos.phobos/std_math_hardware.d: New test. * testsuite/libphobos.phobos/std_math_operations.d: New test. * testsuite/libphobos.phobos/std_math_remainder.d: New test. * testsuite/libphobos.phobos/std_math_rounding.d: New test. * testsuite/libphobos.phobos/std_math_traits.d: New test. * testsuite/libphobos.phobos/std_math_trigonometry.d: New test. * testsuite/libphobos.phobos/std_meta.d: New test. * testsuite/libphobos.phobos/std_mmfile.d: New test. * testsuite/libphobos.phobos/std_numeric.d: New test. * testsuite/libphobos.phobos/std_outbuffer.d: New test. * testsuite/libphobos.phobos/std_package.d: New test. * testsuite/libphobos.phobos/std_parallelism.d: New test. * testsuite/libphobos.phobos/std_path.d: New test. * testsuite/libphobos.phobos/std_random.d: New test. * testsuite/libphobos.phobos/std_range_interfaces.d: New test. * testsuite/libphobos.phobos/std_range_package.d: New test. * testsuite/libphobos.phobos/std_range_primitives.d: New test. * testsuite/libphobos.phobos/std_regex_package.d: New test. * testsuite/libphobos.phobos/std_signals.d: New test. * testsuite/libphobos.phobos/std_socket.d: New test. * testsuite/libphobos.phobos/std_stdio.d: New test. * testsuite/libphobos.phobos/std_string.d: New test. * testsuite/libphobos.phobos/std_sumtype.d: New test. * testsuite/libphobos.phobos/std_traits.d: New test. * testsuite/libphobos.phobos/std_typecons.d: New test. * testsuite/libphobos.phobos/std_typetuple.d: New test. * testsuite/libphobos.phobos/std_uni_package.d: New test. * testsuite/libphobos.phobos/std_uri.d: New test. * testsuite/libphobos.phobos/std_utf.d: New test. * testsuite/libphobos.phobos/std_uuid.d: New test. * testsuite/libphobos.phobos/std_variant.d: New test. * testsuite/libphobos.phobos/std_zlib.d: New test.
This commit is contained in:
parent
ff43f9853d
commit
c2ece13931
108 changed files with 29861 additions and 0 deletions
50
libphobos/testsuite/libphobos.phobos/phobos.exp
Normal file
50
libphobos/testsuite/libphobos.phobos/phobos.exp
Normal file
|
@ -0,0 +1,50 @@
|
|||
# Copyright (C) 2019-2025 Free Software Foundation, Inc.
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with GCC; see the file COPYING3. If not see
|
||||
# <http://www.gnu.org/licenses/>.
|
||||
|
||||
# Immediately exit if we can't run target executables.
|
||||
if { ![isnative] } {
|
||||
return
|
||||
}
|
||||
|
||||
# Skip running test if phobos was not built on the target.
|
||||
if { ![is-effective-target d_runtime_has_std_library] } {
|
||||
return
|
||||
}
|
||||
|
||||
# Gather a list of all tests.
|
||||
set tests [lsort [find $srcdir/$subdir *.d]]
|
||||
|
||||
set version_flags "-fversion=StdUnittest"
|
||||
|
||||
if { [is-effective-target linux_pre_2639] } {
|
||||
lappend version_flags "-fversion=Linux_Pre_2639"
|
||||
}
|
||||
|
||||
set libphobos_skip_tests {
|
||||
# Skip concurrency.d test: SEGVs or hangs on macOS 13+ (PR d/111628).
|
||||
{ libphobos.phobos/std_concurrency.d { x86_64-apple-darwin2[2-9]* } }
|
||||
}
|
||||
|
||||
# Initialize dg.
|
||||
dg-init
|
||||
|
||||
# Main loop.
|
||||
foreach test $tests {
|
||||
dg-runtest $test "" "-Wno-deprecated -fmain $version_flags"
|
||||
}
|
||||
|
||||
# All done.
|
||||
dg-finish
|
|
@ -24,6 +24,11 @@ if { ![is-effective-target d_runtime_has_std_library] } {
|
|||
return
|
||||
}
|
||||
|
||||
# Skip running test if not doing expensive tests.
|
||||
if { ![is-effective-target run_expensive_tests] } {
|
||||
return
|
||||
}
|
||||
|
||||
# Gather a list of all tests.
|
||||
set tests [lsort [filter_libphobos_unittests [find $srcdir/../src "*.d"]]]
|
||||
|
||||
|
|
|
@ -24,6 +24,11 @@ if { ![is-effective-target d_runtime_has_std_library] } {
|
|||
return
|
||||
}
|
||||
|
||||
# Skip running test if not doing expensive tests.
|
||||
if { ![is-effective-target run_expensive_tests] } {
|
||||
return
|
||||
}
|
||||
|
||||
# Gather a list of all tests.
|
||||
set tests [lsort [filter_libphobos_unittests [find $srcdir/../src "*.d"]]]
|
||||
|
||||
|
|
454
libphobos/testsuite/libphobos.phobos/std_algorithm_comparison.d
Normal file
454
libphobos/testsuite/libphobos.phobos/std_algorithm_comparison.d
Normal file
|
@ -0,0 +1,454 @@
|
|||
@safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
assert(3.among(1, 42, 24, 3, 2));
|
||||
|
||||
if (auto pos = "bar".among("foo", "bar", "baz"))
|
||||
assert(pos == 2);
|
||||
else
|
||||
assert(false);
|
||||
|
||||
// 42 is larger than 24
|
||||
assert(42.among!((lhs, rhs) => lhs > rhs)(43, 24, 100) == 2);
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
assert(3.among!(2, 3, 4));
|
||||
assert("bar".among!("foo", "bar", "baz") == 2);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
import std.algorithm.iteration : map;
|
||||
import std.format : format;
|
||||
|
||||
class A
|
||||
{
|
||||
int a;
|
||||
this(int a) {this.a = a;}
|
||||
@property int i() { return a; }
|
||||
}
|
||||
interface I { }
|
||||
class B : I { }
|
||||
|
||||
Object[] arr = [new A(1), new B(), null];
|
||||
|
||||
auto results = arr.map!(castSwitch!(
|
||||
(A a) => "A with a value of %d".format(a.a),
|
||||
(I i) => "derived from I",
|
||||
() => "null reference",
|
||||
))();
|
||||
|
||||
// A is handled directly:
|
||||
assert(results[0] == "A with a value of 1");
|
||||
// B has no handler - it is handled by the handler of I:
|
||||
assert(results[1] == "derived from I");
|
||||
// null is handled by the null handler:
|
||||
assert(results[2] == "null reference");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
class A { }
|
||||
class B { }
|
||||
// Void handlers are allowed if they throw:
|
||||
assertThrown!Exception(
|
||||
new B().castSwitch!(
|
||||
(A a) => 1,
|
||||
(B d) { throw new Exception("B is not allowed!"); }
|
||||
)()
|
||||
);
|
||||
|
||||
// Void handlers are also allowed if all the handlers are void:
|
||||
new A().castSwitch!(
|
||||
(A a) { },
|
||||
(B b) { assert(false); },
|
||||
)();
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
assert(clamp(2, 1, 3) == 2);
|
||||
assert(clamp(0, 1, 3) == 1);
|
||||
assert(clamp(4, 1, 3) == 3);
|
||||
|
||||
assert(clamp(1, 1, 1) == 1);
|
||||
|
||||
assert(clamp(5, -1, 2u) == 2);
|
||||
|
||||
auto x = clamp(42, uint.max, uint.max);
|
||||
static assert(is(typeof(x) == int));
|
||||
assert(x == -1);
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
int result;
|
||||
|
||||
result = cmp("abc", "abc");
|
||||
assert(result == 0);
|
||||
result = cmp("", "");
|
||||
assert(result == 0);
|
||||
result = cmp("abc", "abcd");
|
||||
assert(result < 0);
|
||||
result = cmp("abcd", "abc");
|
||||
assert(result > 0);
|
||||
result = cmp("abc"d, "abd");
|
||||
assert(result < 0);
|
||||
result = cmp("bbc", "abc"w);
|
||||
assert(result > 0);
|
||||
result = cmp("aaa", "aaaa"d);
|
||||
assert(result < 0);
|
||||
result = cmp("aaaa", "aaa"d);
|
||||
assert(result > 0);
|
||||
result = cmp("aaa", "aaa"d);
|
||||
assert(result == 0);
|
||||
result = cmp("aaa"d, "aaa"d);
|
||||
assert(result == 0);
|
||||
result = cmp(cast(int[])[], cast(int[])[]);
|
||||
assert(result == 0);
|
||||
result = cmp([1, 2, 3], [1, 2, 3]);
|
||||
assert(result == 0);
|
||||
result = cmp([1, 3, 2], [1, 2, 3]);
|
||||
assert(result > 0);
|
||||
result = cmp([1, 2, 3], [1L, 2, 3, 4]);
|
||||
assert(result < 0);
|
||||
result = cmp([1L, 2, 3], [1, 2]);
|
||||
assert(result > 0);
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
int result;
|
||||
|
||||
result = cmp!"a > b"("abc", "abc");
|
||||
assert(result == 0);
|
||||
result = cmp!"a > b"("", "");
|
||||
assert(result == 0);
|
||||
result = cmp!"a > b"("abc", "abcd");
|
||||
assert(result < 0);
|
||||
result = cmp!"a > b"("abcd", "abc");
|
||||
assert(result > 0);
|
||||
result = cmp!"a > b"("abc"d, "abd");
|
||||
assert(result > 0);
|
||||
result = cmp!"a > b"("bbc", "abc"w);
|
||||
assert(result < 0);
|
||||
result = cmp!"a > b"("aaa", "aaaa"d);
|
||||
assert(result < 0);
|
||||
result = cmp!"a > b"("aaaa", "aaa"d);
|
||||
assert(result > 0);
|
||||
result = cmp!"a > b"("aaa", "aaa"d);
|
||||
assert(result == 0);
|
||||
result = cmp("aaa"d, "aaa"d);
|
||||
assert(result == 0);
|
||||
result = cmp!"a > b"(cast(int[])[], cast(int[])[]);
|
||||
assert(result == 0);
|
||||
result = cmp!"a > b"([1, 2, 3], [1, 2, 3]);
|
||||
assert(result == 0);
|
||||
result = cmp!"a > b"([1, 3, 2], [1, 2, 3]);
|
||||
assert(result < 0);
|
||||
result = cmp!"a > b"([1, 2, 3], [1L, 2, 3, 4]);
|
||||
assert(result < 0);
|
||||
result = cmp!"a > b"([1L, 2, 3], [1, 2]);
|
||||
assert(result > 0);
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.math.operations : isClose;
|
||||
|
||||
int[4] a = [ 1, 2, 4, 3 ];
|
||||
assert(!equal(a[], a[1..$]));
|
||||
assert(equal(a[], a[]));
|
||||
assert(equal!((a, b) => a == b)(a[], a[]));
|
||||
|
||||
// different types
|
||||
double[4] b = [ 1.0, 2, 4, 3];
|
||||
assert(!equal(a[], b[1..$]));
|
||||
assert(equal(a[], b[]));
|
||||
|
||||
// predicated: ensure that two vectors are approximately equal
|
||||
double[4] c = [ 1.0000000005, 2, 4, 3];
|
||||
assert(equal!isClose(b[], c[]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : iota, chunks;
|
||||
assert(equal!(equal!equal)(
|
||||
[[[0, 1], [2, 3]], [[4, 5], [6, 7]]],
|
||||
iota(0, 8).chunks(2).chunks(2)
|
||||
));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
with(EditOp)
|
||||
{
|
||||
assert(levenshteinDistanceAndPath("foo", "foobar")[1] == [none, none, none, insert, insert, insert]);
|
||||
assert(levenshteinDistanceAndPath("banana", "fazan")[1] == [substitute, none, substitute, none, none, remove]);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
import std.algorithm.iteration : filter;
|
||||
import std.uni : toUpper;
|
||||
|
||||
assert(levenshteinDistance("cat", "rat") == 1);
|
||||
assert(levenshteinDistance("parks", "spark") == 2);
|
||||
assert(levenshteinDistance("abcde", "abcde") == 0);
|
||||
assert(levenshteinDistance("abcde", "abCde") == 1);
|
||||
assert(levenshteinDistance("kitten", "sitting") == 3);
|
||||
assert(levenshteinDistance!((a, b) => toUpper(a) == toUpper(b))
|
||||
("parks", "SPARK") == 2);
|
||||
assert(levenshteinDistance("parks".filter!"true", "spark".filter!"true") == 2);
|
||||
assert(levenshteinDistance("ID", "I♥D") == 1);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
string a = "Saturday", b = "Sundays";
|
||||
auto p = levenshteinDistanceAndPath(a, b);
|
||||
assert(p[0] == 4);
|
||||
assert(equal(p[1], "nrrnsnnni"));
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
int a = 5;
|
||||
short b = 6;
|
||||
double c = 2;
|
||||
auto d = max(a, b);
|
||||
assert(is(typeof(d) == int));
|
||||
assert(d == 6);
|
||||
auto e = min(a, b, c);
|
||||
assert(is(typeof(e) == double));
|
||||
assert(e == 2);
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
int a = 5;
|
||||
short b = 6;
|
||||
double c = 2;
|
||||
auto d = min(a, b);
|
||||
static assert(is(typeof(d) == int));
|
||||
assert(d == 5);
|
||||
auto e = min(a, b, c);
|
||||
static assert(is(typeof(e) == double));
|
||||
assert(e == 2);
|
||||
ulong f = 0xffff_ffff_ffff;
|
||||
const uint g = min(f, 0xffff_0000);
|
||||
assert(g == 0xffff_0000);
|
||||
dchar h = 100;
|
||||
uint i = 101;
|
||||
static assert(is(typeof(min(h, i)) == dchar));
|
||||
static assert(is(typeof(min(i, h)) == uint));
|
||||
assert(min(h, i) == 100);
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
int a = -10;
|
||||
uint f = 10;
|
||||
static assert(is(typeof(min(a, f)) == int));
|
||||
assert(min(a, f) == -10);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
import std.datetime;
|
||||
assert(min(Date(2012, 12, 21), Date(1982, 1, 4)) == Date(1982, 1, 4));
|
||||
assert(min(Date(1982, 1, 4), Date(2012, 12, 21)) == Date(1982, 1, 4));
|
||||
assert(min(Date(1982, 1, 4), Date.min) == Date.min);
|
||||
assert(min(Date.min, Date(1982, 1, 4)) == Date.min);
|
||||
assert(min(Date(1982, 1, 4), Date.max) == Date(1982, 1, 4));
|
||||
assert(min(Date.max, Date(1982, 1, 4)) == Date(1982, 1, 4));
|
||||
assert(min(Date.min, Date.max) == Date.min);
|
||||
assert(min(Date.max, Date.min) == Date.min);
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
int[6] x = [ 1, 5, 2, 7, 4, 3 ];
|
||||
double[6] y = [ 1.0, 5, 2, 7.3, 4, 8 ];
|
||||
auto m = mismatch(x[], y[]);
|
||||
assert(m[0] == x[3 .. $]);
|
||||
assert(m[1] == y[3 .. $]);
|
||||
|
||||
auto m2 = mismatch(x[], y[], x[], y[]);
|
||||
assert(m2[0] == x[3 .. $]);
|
||||
assert(m2[1] == y[3 .. $]);
|
||||
assert(m2[2] == x[3 .. $]);
|
||||
assert(m2[3] == y[3 .. $]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
string res = 2.predSwitch!"a < b"(
|
||||
1, "less than 1",
|
||||
5, "less than 5",
|
||||
10, "less than 10",
|
||||
"greater or equal to 10");
|
||||
|
||||
assert(res == "less than 5");
|
||||
|
||||
//The arguments are lazy, which allows us to use predSwitch to create
|
||||
//recursive functions:
|
||||
int factorial(int n)
|
||||
{
|
||||
return n.predSwitch!"a <= b"(
|
||||
-1, {throw new Exception("Can not calculate n! for n < 0");}(),
|
||||
0, 1, // 0! = 1
|
||||
n * factorial(n - 1) // n! = n * (n - 1)! for n >= 0
|
||||
);
|
||||
}
|
||||
assert(factorial(3) == 6);
|
||||
|
||||
//Void return expressions are allowed if they always throw:
|
||||
import std.exception : assertThrown;
|
||||
assertThrown!Exception(factorial(-9));
|
||||
}
|
||||
|
||||
@safe nothrow pure unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
assert(isSameLength([1, 2, 3], [4, 5, 6]));
|
||||
assert(isSameLength([1, 2, 3], [4, 5, 6], [7, 8, 9]));
|
||||
assert(isSameLength([0.3, 90.4, 23.7, 119.2], [42.6, 23.6, 95.5, 6.3]));
|
||||
assert(isSameLength("abc", "xyz"));
|
||||
assert(isSameLength("abc", "xyz", [1, 2, 3]));
|
||||
|
||||
int[] a;
|
||||
int[] b;
|
||||
assert(isSameLength(a, b));
|
||||
assert(isSameLength(a, b, a, a, b, b, b));
|
||||
|
||||
assert(!isSameLength([1, 2, 3], [4, 5]));
|
||||
assert(!isSameLength([1, 2, 3], [4, 5, 6], [7, 8]));
|
||||
assert(!isSameLength([0.3, 90.4, 23.7], [42.6, 23.6, 95.5, 6.3]));
|
||||
assert(!isSameLength("abcd", "xyz"));
|
||||
assert(!isSameLength("abcd", "xyz", "123"));
|
||||
assert(!isSameLength("abcd", "xyz", "1234"));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
import std.typecons : Yes;
|
||||
|
||||
assert(isPermutation([1, 2, 3], [3, 2, 1]));
|
||||
assert(isPermutation([1.1, 2.3, 3.5], [2.3, 3.5, 1.1]));
|
||||
assert(isPermutation("abc", "bca"));
|
||||
|
||||
assert(!isPermutation([1, 2], [3, 4]));
|
||||
assert(!isPermutation([1, 1, 2, 3], [1, 2, 2, 3]));
|
||||
assert(!isPermutation([1, 1], [1, 1, 1]));
|
||||
|
||||
// Faster, but allocates GC handled memory
|
||||
assert(isPermutation!(Yes.allocateGC)([1.1, 2.3, 3.5], [2.3, 3.5, 1.1]));
|
||||
assert(!isPermutation!(Yes.allocateGC)([1, 2], [3, 4]));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
const a = 1;
|
||||
const b = 2;
|
||||
auto ab = either(a, b);
|
||||
static assert(is(typeof(ab) == const(int)));
|
||||
assert(ab == a);
|
||||
|
||||
auto c = 2;
|
||||
const d = 3;
|
||||
auto cd = either!(a => a == 3)(c, d); // use predicate
|
||||
static assert(is(typeof(cd) == int));
|
||||
assert(cd == d);
|
||||
|
||||
auto e = 0;
|
||||
const f = 2;
|
||||
auto ef = either(e, f);
|
||||
static assert(is(typeof(ef) == int));
|
||||
assert(ef == f);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
immutable p = 1;
|
||||
immutable q = 2;
|
||||
auto pq = either(p, q);
|
||||
static assert(is(typeof(pq) == immutable(int)));
|
||||
assert(pq == p);
|
||||
|
||||
assert(either(3, 4) == 3);
|
||||
assert(either(0, 4) == 4);
|
||||
assert(either(0, 0) == 0);
|
||||
assert(either("", "a") == "");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.comparison;
|
||||
|
||||
string r = null;
|
||||
assert(either(r, "a") == "a");
|
||||
assert(either("a", "") == "a");
|
||||
|
||||
immutable s = [1, 2];
|
||||
assert(either(s, s) == s);
|
||||
|
||||
assert(either([0, 1], [1, 2]) == [0, 1]);
|
||||
assert(either([0, 1], [1]) == [0, 1]);
|
||||
assert(either("a", "b") == "a");
|
||||
|
||||
static assert(!__traits(compiles, either(1, "a")));
|
||||
static assert(!__traits(compiles, either(1.0, "a")));
|
||||
static assert(!__traits(compiles, either('a', "a")));
|
||||
}
|
||||
|
1004
libphobos/testsuite/libphobos.phobos/std_algorithm_iteration.d
Normal file
1004
libphobos/testsuite/libphobos.phobos/std_algorithm_iteration.d
Normal file
File diff suppressed because it is too large
Load diff
627
libphobos/testsuite/libphobos.phobos/std_algorithm_mutation.d
Normal file
627
libphobos/testsuite/libphobos.phobos/std_algorithm_mutation.d
Normal file
|
@ -0,0 +1,627 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
auto arr = [4, 5, 6, 7, 1, 2, 3];
|
||||
auto p = bringToFront(arr[0 .. 4], arr[4 .. $]);
|
||||
assert(p == arr.length - 4);
|
||||
assert(arr == [ 1, 2, 3, 4, 5, 6, 7 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.container : SList;
|
||||
import std.range.primitives : popFrontN;
|
||||
|
||||
auto list = SList!(int)(4, 5, 6, 7, 1, 2, 3);
|
||||
auto r1 = list[];
|
||||
auto r2 = list[]; popFrontN(r2, 4);
|
||||
assert(equal(r2, [ 1, 2, 3 ]));
|
||||
bringToFront(r1, r2);
|
||||
assert(equal(list[], [ 1, 2, 3, 4, 5, 6, 7 ]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.container : SList;
|
||||
|
||||
auto list = SList!(int)(4, 5, 6, 7);
|
||||
auto vec = [ 1, 2, 3 ];
|
||||
bringToFront(list[], vec);
|
||||
assert(equal(list[], [ 1, 2, 3, 4 ]));
|
||||
assert(equal(vec, [ 5, 6, 7 ]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.string : representation;
|
||||
auto ar = representation("a".dup);
|
||||
auto br = representation("ç".dup);
|
||||
|
||||
bringToFront(ar, br);
|
||||
|
||||
auto a = cast(char[]) ar;
|
||||
auto b = cast(char[]) br;
|
||||
|
||||
// Illegal UTF-8
|
||||
assert(a == "\303");
|
||||
// Illegal UTF-8
|
||||
assert(b == "\247a");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
int[] a = [ 1, 5 ];
|
||||
int[] b = [ 9, 8 ];
|
||||
int[] buf = new int[](a.length + b.length + 10);
|
||||
auto rem = a.copy(buf); // copy a into buf
|
||||
rem = b.copy(rem); // copy b into remainder of buf
|
||||
assert(buf[0 .. a.length + b.length] == [1, 5, 9, 8]);
|
||||
assert(rem.length == 10); // unused slots in buf
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
float[] src = [ 1.0f, 5 ];
|
||||
double[] dest = new double[src.length];
|
||||
src.copy(dest);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.range;
|
||||
int[] src = [ 1, 5, 8, 9, 10 ];
|
||||
auto dest = new int[](3);
|
||||
src.take(dest.length).copy(dest);
|
||||
assert(dest == [ 1, 5, 8 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.algorithm.iteration : filter;
|
||||
int[] src = [ 1, 5, 8, 9, 10, 1, 2, 0 ];
|
||||
auto dest = new int[src.length];
|
||||
auto rem = src
|
||||
.filter!(a => (a & 1) == 1)
|
||||
.copy(dest);
|
||||
assert(dest[0 .. $ - rem.length] == [ 1, 5, 9, 1 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.algorithm, std.range;
|
||||
int[] src = [1, 2, 4];
|
||||
int[] dest = [0, 0, 0, 0, 0];
|
||||
src.retro.copy(dest.retro);
|
||||
assert(dest == [0, 0, 1, 2, 4]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
int[] a = [ 1, 2, 3, 4 ];
|
||||
fill(a, 5);
|
||||
assert(a == [ 5, 5, 5, 5 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
int[] a = [ 1, 2, 3, 4, 5 ];
|
||||
int[] b = [ 8, 9 ];
|
||||
fill(a, b);
|
||||
assert(a == [ 8, 9, 8, 9, 8 ]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import core.stdc.stdlib : malloc, free;
|
||||
|
||||
struct S
|
||||
{
|
||||
int a = 10;
|
||||
}
|
||||
|
||||
auto s = (cast(S*) malloc(5 * S.sizeof))[0 .. 5];
|
||||
initializeAll(s);
|
||||
assert(s == [S(10), S(10), S(10), S(10), S(10)]);
|
||||
|
||||
scope(exit) free(s.ptr);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
Object obj1 = new Object;
|
||||
Object obj2 = obj1;
|
||||
Object obj3;
|
||||
|
||||
move(obj2, obj3);
|
||||
assert(obj3 is obj1);
|
||||
// obj2 unchanged
|
||||
assert(obj2 is obj1);
|
||||
}
|
||||
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
// Structs without destructors are simply copied
|
||||
struct S1
|
||||
{
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
}
|
||||
S1 s11 = { 10, 11 };
|
||||
S1 s12;
|
||||
|
||||
move(s11, s12);
|
||||
|
||||
assert(s12 == S1(10, 11));
|
||||
assert(s11 == s12);
|
||||
|
||||
// But structs with destructors or postblits are reset to their .init value
|
||||
// after copying to the target.
|
||||
struct S2
|
||||
{
|
||||
int a = 1;
|
||||
int b = 2;
|
||||
|
||||
~this() pure nothrow @safe @nogc { }
|
||||
}
|
||||
S2 s21 = { 3, 4 };
|
||||
S2 s22;
|
||||
|
||||
move(s21, s22);
|
||||
|
||||
assert(s21 == S2(1, 2));
|
||||
assert(s22 == S2(3, 4));
|
||||
}
|
||||
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
struct S
|
||||
{
|
||||
int a = 1;
|
||||
@disable this(this);
|
||||
~this() pure nothrow @safe @nogc {}
|
||||
}
|
||||
S s1;
|
||||
s1.a = 2;
|
||||
S s2 = move(s1);
|
||||
assert(s1.a == 1);
|
||||
assert(s2.a == 2);
|
||||
}
|
||||
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
struct S
|
||||
{
|
||||
int a;
|
||||
void opPostMove(const ref S old)
|
||||
{
|
||||
assert(a == old.a);
|
||||
a++;
|
||||
}
|
||||
}
|
||||
S s1;
|
||||
s1.a = 41;
|
||||
S s2 = move(s1);
|
||||
assert(s2.a == 42);
|
||||
}
|
||||
|
||||
pure nothrow @nogc @system unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
static struct Foo
|
||||
{
|
||||
pure nothrow @nogc:
|
||||
this(int* ptr) { _ptr = ptr; }
|
||||
~this() { if (_ptr) ++*_ptr; }
|
||||
int* _ptr;
|
||||
}
|
||||
|
||||
int val;
|
||||
Foo foo1 = void; // uninitialized
|
||||
auto foo2 = Foo(&val); // initialized
|
||||
assert(foo2._ptr is &val);
|
||||
|
||||
// Using `move(foo2, foo1)` would have an undefined effect because it would destroy
|
||||
// the uninitialized foo1.
|
||||
// moveEmplace directly overwrites foo1 without destroying or initializing it first.
|
||||
moveEmplace(foo2, foo1);
|
||||
assert(foo1._ptr is &val);
|
||||
assert(foo2._ptr is null);
|
||||
assert(val == 0);
|
||||
}
|
||||
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
int[3] a = [ 1, 2, 3 ];
|
||||
int[5] b;
|
||||
assert(moveAll(a[], b[]) is b[3 .. $]);
|
||||
assert(a[] == b[0 .. 3]);
|
||||
int[3] cmp = [ 1, 2, 3 ];
|
||||
assert(a[] == cmp[]);
|
||||
}
|
||||
|
||||
pure nothrow @nogc @system unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
static struct Foo
|
||||
{
|
||||
~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
|
||||
int* _ptr;
|
||||
}
|
||||
int[3] refs = [0, 1, 2];
|
||||
Foo[3] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2])];
|
||||
Foo[5] dst = void;
|
||||
|
||||
auto tail = moveEmplaceAll(src[], dst[]); // move 3 value from src over dst
|
||||
assert(tail.length == 2); // returns remaining uninitialized values
|
||||
initializeAll(tail);
|
||||
|
||||
import std.algorithm.searching : all;
|
||||
assert(src[].all!(e => e._ptr is null));
|
||||
assert(dst[0 .. 3].all!(e => e._ptr !is null));
|
||||
}
|
||||
|
||||
pure nothrow @safe @nogc unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
int[5] a = [ 1, 2, 3, 4, 5 ];
|
||||
int[3] b;
|
||||
assert(moveSome(a[], b[])[0] is a[3 .. $]);
|
||||
assert(a[0 .. 3] == b);
|
||||
assert(a == [ 1, 2, 3, 4, 5 ]);
|
||||
}
|
||||
|
||||
pure nothrow @nogc @system unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
static struct Foo
|
||||
{
|
||||
~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
|
||||
int* _ptr;
|
||||
}
|
||||
int[4] refs = [0, 1, 2, 3];
|
||||
Foo[4] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2]), Foo(&refs[3])];
|
||||
Foo[3] dst = void;
|
||||
|
||||
auto res = moveEmplaceSome(src[], dst[]);
|
||||
assert(res.length == 2);
|
||||
|
||||
import std.algorithm.searching : all;
|
||||
assert(src[0 .. 3].all!(e => e._ptr is null));
|
||||
assert(src[3]._ptr !is null);
|
||||
assert(dst[].all!(e => e._ptr !is null));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
int[] a = [0, 1, 2, 3];
|
||||
assert(remove!(SwapStrategy.stable)(a, 1) == [0, 2, 3]);
|
||||
a = [0, 1, 2, 3];
|
||||
assert(remove!(SwapStrategy.unstable)(a, 1) == [0, 3, 2]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.algorithm.sorting : partition;
|
||||
|
||||
// Put stuff greater than 3 on the left
|
||||
auto arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
assert(partition!(a => a > 3, SwapStrategy.stable)(arr) == [1, 2, 3]);
|
||||
assert(arr == [4, 5, 6, 7, 8, 9, 10, 1, 2, 3]);
|
||||
|
||||
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
assert(partition!(a => a > 3, SwapStrategy.semistable)(arr) == [2, 3, 1]);
|
||||
assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1]);
|
||||
|
||||
arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
assert(partition!(a => a > 3, SwapStrategy.unstable)(arr) == [3, 2, 1]);
|
||||
assert(arr == [10, 9, 8, 4, 5, 6, 7, 3, 2, 1]);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto a = [ 0, 1, 2, 3, 4, 5 ];
|
||||
assert(remove!(SwapStrategy.stable)(a, 1) == [ 0, 2, 3, 4, 5 ]);
|
||||
a = [ 0, 1, 2, 3, 4, 5 ];
|
||||
assert(remove!(SwapStrategy.stable)(a, 1, 3) == [ 0, 2, 4, 5] );
|
||||
a = [ 0, 1, 2, 3, 4, 5 ];
|
||||
assert(remove!(SwapStrategy.stable)(a, 1, tuple(3, 6)) == [ 0, 2 ]);
|
||||
|
||||
a = [ 0, 1, 2, 3, 4, 5 ];
|
||||
assert(remove!(SwapStrategy.unstable)(a, 1) == [0, 5, 2, 3, 4]);
|
||||
a = [ 0, 1, 2, 3, 4, 5 ];
|
||||
assert(remove!(SwapStrategy.unstable)(a, tuple(1, 4)) == [0, 5, 4]);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.typecons : tuple;
|
||||
|
||||
// Delete an index
|
||||
assert([4, 5, 6].remove(1) == [4, 6]);
|
||||
|
||||
// Delete multiple indices
|
||||
assert([4, 5, 6, 7, 8].remove(1, 3) == [4, 6, 8]);
|
||||
|
||||
// Use an indices range
|
||||
assert([4, 5, 6, 7, 8].remove(tuple(1, 3)) == [4, 7, 8]);
|
||||
|
||||
// Use an indices range and individual indices
|
||||
assert([4, 5, 6, 7, 8].remove(0, tuple(1, 3), 4) == [7]);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
assert([5, 6, 7, 8].remove!(SwapStrategy.stable)(1) == [5, 7, 8]);
|
||||
assert([5, 6, 7, 8].remove!(SwapStrategy.unstable)(1) == [5, 8, 7]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
static immutable base = [1, 2, 3, 2, 4, 2, 5, 2];
|
||||
|
||||
int[] arr = base[].dup;
|
||||
|
||||
// using a string-based predicate
|
||||
assert(remove!("a == 2")(arr) == [ 1, 3, 4, 5 ]);
|
||||
|
||||
// The original array contents have been modified,
|
||||
// so we need to reset it to its original state.
|
||||
// The length is unmodified however.
|
||||
arr[] = base[];
|
||||
|
||||
// using a lambda predicate
|
||||
assert(remove!(a => a == 2)(arr) == [ 1, 3, 4, 5 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
int[] arr = [ 1, 2, 3 ];
|
||||
assert(arr.reverse == [ 3, 2, 1 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
char[] arr = "hello\U00010143\u0100\U00010143".dup;
|
||||
assert(arr.reverse == "\U00010143\u0100\U00010143olleh");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
assert(" foobar ".strip(' ') == "foobar");
|
||||
assert("00223.444500".strip('0') == "223.4445");
|
||||
assert("ëëêéüŗōpéêëë".strip('ë') == "êéüŗōpéê");
|
||||
assert([1, 1, 0, 1, 1].strip(1) == [0]);
|
||||
assert([0.0, 0.01, 0.01, 0.0].strip(0).length == 2);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
assert(" foobar ".strip!(a => a == ' ')() == "foobar");
|
||||
assert("00223.444500".strip!(a => a == '0')() == "223.4445");
|
||||
assert("ëëêéüŗōpéêëë".strip!(a => a == 'ë')() == "êéüŗōpéê");
|
||||
assert([1, 1, 0, 1, 1].strip!(a => a == 1)() == [0]);
|
||||
assert([0.0, 0.01, 0.5, 0.6, 0.01, 0.0].strip!(a => a < 0.4)().length == 2);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
assert(" foobar ".stripLeft(' ') == "foobar ");
|
||||
assert("00223.444500".stripLeft('0') == "223.444500");
|
||||
assert("ůůűniçodêéé".stripLeft('ů') == "űniçodêéé");
|
||||
assert([1, 1, 0, 1, 1].stripLeft(1) == [0, 1, 1]);
|
||||
assert([0.0, 0.01, 0.01, 0.0].stripLeft(0).length == 3);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
assert(" foobar ".stripLeft!(a => a == ' ')() == "foobar ");
|
||||
assert("00223.444500".stripLeft!(a => a == '0')() == "223.444500");
|
||||
assert("ůůűniçodêéé".stripLeft!(a => a == 'ů')() == "űniçodêéé");
|
||||
assert([1, 1, 0, 1, 1].stripLeft!(a => a == 1)() == [0, 1, 1]);
|
||||
assert([0.0, 0.01, 0.10, 0.5, 0.6].stripLeft!(a => a < 0.4)().length == 2);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
assert(" foobar ".stripRight(' ') == " foobar");
|
||||
assert("00223.444500".stripRight('0') == "00223.4445");
|
||||
assert("ùniçodêéé".stripRight('é') == "ùniçodê");
|
||||
assert([1, 1, 0, 1, 1].stripRight(1) == [1, 1, 0]);
|
||||
assert([0.0, 0.01, 0.01, 0.0].stripRight(0).length == 3);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
assert(" foobar ".stripRight!(a => a == ' ')() == " foobar");
|
||||
assert("00223.444500".stripRight!(a => a == '0')() == "00223.4445");
|
||||
assert("ùniçodêéé".stripRight!(a => a == 'é')() == "ùniçodê");
|
||||
assert([1, 1, 0, 1, 1].stripRight!(a => a == 1)() == [1, 1, 0]);
|
||||
assert([0.0, 0.01, 0.10, 0.5, 0.6].stripRight!(a => a > 0.4)().length == 3);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
// Swapping POD (plain old data) types:
|
||||
int a = 42, b = 34;
|
||||
swap(a, b);
|
||||
assert(a == 34 && b == 42);
|
||||
|
||||
// Swapping structs with indirection:
|
||||
static struct S { int x; char c; int[] y; }
|
||||
S s1 = { 0, 'z', [ 1, 2 ] };
|
||||
S s2 = { 42, 'a', [ 4, 6 ] };
|
||||
swap(s1, s2);
|
||||
assert(s1.x == 42);
|
||||
assert(s1.c == 'a');
|
||||
assert(s1.y == [ 4, 6 ]);
|
||||
|
||||
assert(s2.x == 0);
|
||||
assert(s2.c == 'z');
|
||||
assert(s2.y == [ 1, 2 ]);
|
||||
|
||||
// Immutables cannot be swapped:
|
||||
immutable int imm1 = 1, imm2 = 2;
|
||||
static assert(!__traits(compiles, swap(imm1, imm2)));
|
||||
|
||||
int c = imm1 + 0;
|
||||
int d = imm2 + 0;
|
||||
swap(c, d);
|
||||
assert(c == 2);
|
||||
assert(d == 1);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
// Non-copyable types can still be swapped.
|
||||
static struct NoCopy
|
||||
{
|
||||
this(this) { assert(0); }
|
||||
int n;
|
||||
string s;
|
||||
}
|
||||
NoCopy nc1, nc2;
|
||||
nc1.n = 127; nc1.s = "abc";
|
||||
nc2.n = 513; nc2.s = "uvwxyz";
|
||||
|
||||
swap(nc1, nc2);
|
||||
assert(nc1.n == 513 && nc1.s == "uvwxyz");
|
||||
assert(nc2.n == 127 && nc2.s == "abc");
|
||||
|
||||
swap(nc1, nc1);
|
||||
swap(nc2, nc2);
|
||||
assert(nc1.n == 513 && nc1.s == "uvwxyz");
|
||||
assert(nc2.n == 127 && nc2.s == "abc");
|
||||
|
||||
// Types containing non-copyable fields can also be swapped.
|
||||
static struct NoCopyHolder
|
||||
{
|
||||
NoCopy noCopy;
|
||||
}
|
||||
NoCopyHolder h1, h2;
|
||||
h1.noCopy.n = 31; h1.noCopy.s = "abc";
|
||||
h2.noCopy.n = 65; h2.noCopy.s = null;
|
||||
|
||||
swap(h1, h2);
|
||||
assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
|
||||
assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
|
||||
|
||||
swap(h1, h1);
|
||||
swap(h2, h2);
|
||||
assert(h1.noCopy.n == 65 && h1.noCopy.s == null);
|
||||
assert(h2.noCopy.n == 31 && h2.noCopy.s == "abc");
|
||||
|
||||
// Const types cannot be swapped.
|
||||
const NoCopy const1, const2;
|
||||
assert(const1.n == 0 && const2.n == 0);
|
||||
static assert(!__traits(compiles, swap(const1, const2)));
|
||||
}
|
||||
|
||||
pure @safe nothrow unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
auto a = [1, 2, 3];
|
||||
a.swapAt(1, 2);
|
||||
assert(a.equal([1, 3, 2]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import std.range : empty;
|
||||
int[] a = [ 100, 101, 102, 103 ];
|
||||
int[] b = [ 0, 1, 2, 3 ];
|
||||
auto c = swapRanges(a[1 .. 3], b[2 .. 4]);
|
||||
assert(c[0].empty && c[1].empty);
|
||||
assert(a == [ 100, 2, 3, 103 ]);
|
||||
assert(b == [ 0, 1, 101, 102 ]);
|
||||
}
|
||||
|
||||
nothrow @system unittest
|
||||
{
|
||||
import std.algorithm.mutation;
|
||||
|
||||
import core.stdc.stdlib : malloc, free;
|
||||
|
||||
auto s = (cast(int*) malloc(5 * int.sizeof))[0 .. 5];
|
||||
uninitializedFill(s, 42);
|
||||
assert(s == [ 42, 42, 42, 42, 42 ]);
|
||||
|
||||
scope(exit) free(s.ptr);
|
||||
}
|
||||
|
668
libphobos/testsuite/libphobos.phobos/std_algorithm_searching.d
Normal file
668
libphobos/testsuite/libphobos.phobos/std_algorithm_searching.d
Normal file
|
@ -0,0 +1,668 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
assert( all!"a & 1"([1, 3, 5, 7, 9]));
|
||||
assert(!all!"a & 1"([1, 2, 3, 5, 7, 9]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
int[3] vals = [5, 3, 18];
|
||||
assert( all(vals[]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.ascii : isWhite;
|
||||
assert( all!(any!isWhite)(["a a", "b b"]));
|
||||
assert(!any!(all!isWhite)(["a a", "b b"]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
int[3] vals1 = [0, 0, 0];
|
||||
assert(!any(vals1[])); //none of vals1 evaluate to true
|
||||
|
||||
int[3] vals2 = [2, 0, 2];
|
||||
assert( any(vals2[]));
|
||||
assert(!all(vals2[]));
|
||||
|
||||
int[3] vals3 = [3, 3, 3];
|
||||
assert( any(vals3[]));
|
||||
assert( all(vals3[]));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
auto s = "1 + (2 * (3 + 1 / 2)";
|
||||
assert(!balancedParens(s, '(', ')'));
|
||||
s = "1 + (2 * (3 + 1) / 2)";
|
||||
assert(balancedParens(s, '(', ')'));
|
||||
s = "1 + (2 * (3 + 1) / 2)";
|
||||
assert(!balancedParens(s, '(', ')', 0));
|
||||
s = "1 + (2 * 3 + 1) / (2 - 5)";
|
||||
assert(balancedParens(s, '(', ')', 0));
|
||||
s = "f(x) = ⌈x⌉";
|
||||
assert(balancedParens(s, '⌈', '⌉'));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
auto bmFinder = boyerMooreFinder("TG");
|
||||
|
||||
string r = "TAGTGCCTGA";
|
||||
// search for the first match in the haystack r
|
||||
r = bmFinder.beFound(r);
|
||||
assert(r == "TGCCTGA");
|
||||
|
||||
// continue search in haystack
|
||||
r = bmFinder.beFound(r[2 .. $]);
|
||||
assert(r == "TGA");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
assert(commonPrefix("hello, world", "hello, there") == "hello, ");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
// count elements in range
|
||||
int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
|
||||
assert(count(a, 2) == 3);
|
||||
assert(count!("a > b")(a, 2) == 5);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.uni : toLower;
|
||||
// count range in range
|
||||
assert(count("abcadfabf", "ab") == 2);
|
||||
assert(count("ababab", "abab") == 1);
|
||||
assert(count("ababab", "abx") == 0);
|
||||
// fuzzy count range in range
|
||||
assert(count!((a, b) => toLower(a) == toLower(b))("AbcAdFaBf", "ab") == 2);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
// count elements in range
|
||||
int[] a = [ 1, 2, 4, 3, 2, 5, 3, 2, 4 ];
|
||||
assert(count(a) == 9);
|
||||
// count predicate in range
|
||||
assert(count!("a > 2")(a) == 5);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
assert(countUntil("hello world", "world") == 6);
|
||||
assert(countUntil("hello world", 'r') == 8);
|
||||
assert(countUntil("hello world", "programming") == -1);
|
||||
assert(countUntil("日本語", "本語") == 1);
|
||||
assert(countUntil("日本語", '語') == 2);
|
||||
assert(countUntil("日本語", "五") == -1);
|
||||
assert(countUntil("日本語", '五') == -1);
|
||||
assert(countUntil([0, 7, 12, 22, 9], [12, 22]) == 2);
|
||||
assert(countUntil([0, 7, 12, 22, 9], 9) == 4);
|
||||
assert(countUntil!"a > b"([0, 7, 12, 22, 9], 20) == 3);
|
||||
|
||||
// supports multiple needles
|
||||
auto res = "...hello".countUntil("ha", "he");
|
||||
assert(res.steps == 3);
|
||||
assert(res.needle == 1);
|
||||
|
||||
// returns -1 if no needle was found
|
||||
res = "hello".countUntil("ha", "hu");
|
||||
assert(res.steps == -1);
|
||||
assert(res.needle == -1);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.ascii : isDigit;
|
||||
import std.uni : isWhite;
|
||||
|
||||
assert(countUntil!(isWhite)("hello world") == 5);
|
||||
assert(countUntil!(isDigit)("hello world") == -1);
|
||||
assert(countUntil!"a > 20"([0, 7, 12, 22, 9]) == 3);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.ascii : isAlpha;
|
||||
assert("abc".endsWith!(a => a.isAlpha));
|
||||
assert("abc".endsWith!isAlpha);
|
||||
|
||||
assert(!"ab1".endsWith!(a => a.isAlpha));
|
||||
|
||||
assert(!"ab1".endsWith!isAlpha);
|
||||
assert(!"".endsWith!(a => a.isAlpha));
|
||||
|
||||
import std.algorithm.comparison : among;
|
||||
assert("abc".endsWith!(a => a.among('c', 'd') != 0));
|
||||
assert(!"abc".endsWith!(a => a.among('a', 'b') != 0));
|
||||
|
||||
assert(endsWith("abc", ""));
|
||||
assert(!endsWith("abc", "b"));
|
||||
assert(endsWith("abc", "a", 'c') == 2);
|
||||
assert(endsWith("abc", "c", "a") == 1);
|
||||
assert(endsWith("abc", "c", "c") == 1);
|
||||
assert(endsWith("abc", "bc", "c") == 2);
|
||||
assert(endsWith("abc", "x", "c", "b") == 2);
|
||||
assert(endsWith("abc", "x", "aa", "bc") == 3);
|
||||
assert(endsWith("abc", "x", "aaa", "sab") == 0);
|
||||
assert(endsWith("abc", "x", "aaa", 'c', "sab") == 3);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
auto arr = [ 1, 2, 3, 4, 1 ];
|
||||
assert(find!("a > 2")(arr) == [ 3, 4, 1 ]);
|
||||
|
||||
// with predicate alias
|
||||
bool pred(int e) => e + 1 > 1.5;
|
||||
assert(find!(pred)(arr) == arr);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.range.primitives;
|
||||
|
||||
auto arr = [1, 2, 4, 4, 4, 4, 5, 6, 9];
|
||||
assert(arr.find(4) == [4, 4, 4, 4, 5, 6, 9]);
|
||||
assert(arr.find(1) == arr);
|
||||
assert(arr.find(9) == [9]);
|
||||
assert(arr.find!((e, n) => e > n)(4) == [5, 6, 9]);
|
||||
assert(arr.find!((e, n) => e < n)(4) == arr);
|
||||
assert(arr.find(0).empty);
|
||||
assert(arr.find(10).empty);
|
||||
assert(arr.find(8).empty);
|
||||
|
||||
assert(find("hello, world", ',') == ", world");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.range.primitives;
|
||||
import std.uni : toLower;
|
||||
|
||||
string[] s = ["Hello", "world", "!"];
|
||||
assert(s.find!((e, n) => toLower(e) == n)("hello") == s);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.container : SList;
|
||||
import std.range.primitives : empty;
|
||||
import std.typecons : Tuple;
|
||||
|
||||
assert(find("hello, world", "World").empty);
|
||||
assert(find("hello, world", "wo") == "world");
|
||||
assert([1, 2, 3, 4].find(SList!int(2, 3)[]) == [2, 3, 4]);
|
||||
alias C = Tuple!(int, "x", int, "y");
|
||||
auto a = [C(1,0), C(2,0), C(3,1), C(4,0)];
|
||||
assert(a.find!"a.x == b"([2, 3]) == [C(2,0), C(3,1), C(4,0)]);
|
||||
assert(a[1 .. $].find!"a.x == b"([2, 3]) == [C(2,0), C(3,1), C(4,0)]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.typecons : tuple;
|
||||
int[] a = [ 1, 4, 2, 3 ];
|
||||
assert(find(a, 4) == [ 4, 2, 3 ]);
|
||||
assert(find(a, [ 1, 4 ]) == [ 1, 4, 2, 3 ]);
|
||||
assert(find(a, [ 1, 3 ], 4) == tuple([ 4, 2, 3 ], 2));
|
||||
// Mixed types allowed if comparable
|
||||
assert(find(a, 5, [ 1.2, 3.5 ], 2.0) == tuple([ 2, 3 ], 3));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.range.primitives : empty;
|
||||
int[] a = [ -1, 0, 1, 2, 3, 4, 5 ];
|
||||
int[] b = [ 1, 2, 3 ];
|
||||
|
||||
assert(find(a, boyerMooreFinder(b)) == [ 1, 2, 3, 4, 5 ]);
|
||||
assert(find(b, boyerMooreFinder(a)).empty);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
const arr = [0, 1, 2, 3];
|
||||
assert(canFind(arr, 2));
|
||||
assert(!canFind(arr, 4));
|
||||
|
||||
// find one of several needles
|
||||
assert(arr.canFind(3, 2));
|
||||
assert(arr.canFind(3, 2) == 2); // second needle found
|
||||
assert(arr.canFind([1, 3], 2) == 2);
|
||||
|
||||
assert(canFind(arr, [1, 2], [2, 3]));
|
||||
assert(canFind(arr, [1, 2], [2, 3]) == 1);
|
||||
assert(canFind(arr, [1, 7], [2, 3]));
|
||||
assert(canFind(arr, [1, 7], [2, 3]) == 2);
|
||||
assert(!canFind(arr, [1, 3], [2, 4]));
|
||||
assert(canFind(arr, [1, 3], [2, 4]) == 0);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
auto words = [
|
||||
"apple",
|
||||
"beeswax",
|
||||
"cardboard"
|
||||
];
|
||||
assert(!canFind(words, "bees"));
|
||||
assert( canFind!((string elem, string needle) => elem.startsWith(needle))(words, "bees"));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
string s1 = "aaa111aaa";
|
||||
string s2 = "aaa222aaa";
|
||||
string s3 = "aaa333aaa";
|
||||
string s4 = "aaa444aaa";
|
||||
const hay = [s1, s2, s3, s4];
|
||||
assert(hay.canFind!(e => e.canFind("111", "222")));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
int[] a = [ 11, 10, 10, 9, 8, 8, 7, 8, 9 ];
|
||||
auto r = findAdjacent(a);
|
||||
assert(r == [ 10, 10, 9, 8, 8, 7, 8, 9 ]);
|
||||
auto p = findAdjacent!("a < b")(a);
|
||||
assert(p == [ 7, 8, 9 ]);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
int[] a = [ -1, 0, 1, 2, 3, 4, 5 ];
|
||||
int[] b = [ 3, 1, 2 ];
|
||||
assert(findAmong(a, b) == a[2 .. $]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.range.primitives : empty;
|
||||
// Needle is found; s is replaced by the substring following the first
|
||||
// occurrence of the needle.
|
||||
string s = "abcdef";
|
||||
assert(findSkip(s, "cd") && s == "ef");
|
||||
|
||||
// Needle is not found; s is left untouched.
|
||||
s = "abcdef";
|
||||
assert(!findSkip(s, "cxd") && s == "abcdef");
|
||||
|
||||
// If the needle occurs at the end of the range, the range is left empty.
|
||||
s = "abcdef";
|
||||
assert(findSkip(s, "def") && s.empty);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.ascii : isWhite;
|
||||
string s = " abc";
|
||||
assert(findSkip!isWhite(s) && s == "abc");
|
||||
assert(!findSkip!isWhite(s) && s == "abc");
|
||||
|
||||
s = " ";
|
||||
assert(findSkip!isWhite(s) == 2);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
// findSplit returns a triplet
|
||||
if (auto split = "dlang-rocks".findSplit("-"))
|
||||
{
|
||||
assert(split[0] == "dlang");
|
||||
assert(split[1] == "-");
|
||||
assert(split[2] == "rocks");
|
||||
}
|
||||
else assert(0);
|
||||
|
||||
// findSplitBefore returns 2 ranges
|
||||
if (const split = [2, 3, 2, 3, 4, 1].findSplitBefore!"a > b"([2, 2]))
|
||||
{
|
||||
assert(split[0] == [2, 3, 2]);
|
||||
// [3, 4] each greater than [2, 2]
|
||||
assert(split[1] == [3, 4, 1]);
|
||||
}
|
||||
else assert(0);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.range.primitives : empty;
|
||||
|
||||
auto a = "Carl Sagan Memorial Station";
|
||||
auto r = findSplit(a, "Velikovsky");
|
||||
import std.typecons : isTuple;
|
||||
static assert(isTuple!(typeof(r.asTuple)));
|
||||
static assert(isTuple!(typeof(r)));
|
||||
assert(!r);
|
||||
assert(r[0] == a);
|
||||
assert(r[1].empty);
|
||||
assert(r[2].empty);
|
||||
r = findSplit(a, " ");
|
||||
assert(r[0] == "Carl");
|
||||
assert(r[1] == " ");
|
||||
assert(r[2] == "Sagan Memorial Station");
|
||||
if (const r1 = findSplitBefore(a, "Sagan"))
|
||||
{
|
||||
assert(r1);
|
||||
assert(r1[0] == "Carl ");
|
||||
assert(r1[1] == "Sagan Memorial Station");
|
||||
}
|
||||
if (const r2 = findSplitAfter(a, "Sagan"))
|
||||
{
|
||||
assert(r2);
|
||||
assert(r2[0] == "Carl Sagan");
|
||||
assert(r2[1] == " Memorial Station");
|
||||
}
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.range : only;
|
||||
assert([1, 2, 3, 4].findSplitBefore(only(3))[0] == [1, 2]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.conv : text;
|
||||
import std.typecons : tuple;
|
||||
|
||||
int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
|
||||
// Minimum is 1 and occurs 3 times
|
||||
assert(a.minCount == tuple(1, 3));
|
||||
// Maximum is 4 and occurs 2 times
|
||||
assert(a.maxCount == tuple(4, 2));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.range : enumerate;
|
||||
import std.typecons : tuple;
|
||||
|
||||
assert([2, 7, 1, 3].minElement == 1);
|
||||
|
||||
// allows to get the index of an element too
|
||||
assert([5, 3, 7, 9].enumerate.minElement!"a.value" == tuple(1, 3));
|
||||
|
||||
// any custom accessor can be passed
|
||||
assert([[0, 4], [1, 2]].minElement!"a[1]" == [1, 2]);
|
||||
|
||||
// can be seeded
|
||||
int[] arr;
|
||||
assert(arr.minElement(1) == 1);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.range : enumerate;
|
||||
import std.typecons : tuple;
|
||||
assert([2, 1, 4, 3].maxElement == 4);
|
||||
|
||||
// allows to get the index of an element too
|
||||
assert([2, 1, 4, 3].enumerate.maxElement!"a.value" == tuple(2, 4));
|
||||
|
||||
// any custom accessor can be passed
|
||||
assert([[0, 4], [1, 2]].maxElement!"a[1]" == [0, 4]);
|
||||
|
||||
// can be seeded
|
||||
int[] arr;
|
||||
assert(arr.minElement(1) == 1);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
assert(extrema([5,2,9,4,1]) == [1, 9]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
int[] a = [ 2, 3, 4, 1, 2, 4, 1, 1, 2 ];
|
||||
// Minimum is 1 and first occurs in position 3
|
||||
assert(a.minPos == [ 1, 2, 4, 1, 1, 2 ]);
|
||||
// Maximum is 4 and first occurs in position 2
|
||||
assert(a.maxPos == [ 4, 1, 2, 4, 1, 1, 2 ]);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
int[] a = [2, 3, 4, 1, 2, 4, 1, 1, 2];
|
||||
|
||||
// Minimum is 1 and first occurs in position 3
|
||||
assert(a.minIndex == 3);
|
||||
// Get maximum index with minIndex
|
||||
assert(a.minIndex!"a > b" == 2);
|
||||
|
||||
// Range is empty, so return value is -1
|
||||
int[] b;
|
||||
assert(b.minIndex == -1);
|
||||
|
||||
// Works with more custom types
|
||||
struct Dog { int age; }
|
||||
Dog[] dogs = [Dog(10), Dog(5), Dog(15)];
|
||||
assert(dogs.minIndex!"a.age < b.age" == 1);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
// Maximum is 4 and first occurs in position 2
|
||||
int[] a = [2, 3, 4, 1, 2, 4, 1, 1, 2];
|
||||
assert(a.maxIndex == 2);
|
||||
|
||||
// Empty range
|
||||
int[] b;
|
||||
assert(b.maxIndex == -1);
|
||||
|
||||
// Works with more custom types
|
||||
struct Dog { int age; }
|
||||
Dog[] dogs = [Dog(10), Dog(15), Dog(5)];
|
||||
assert(dogs.maxIndex!"a.age < b.age" == 1);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
auto s1 = "Hello world";
|
||||
assert(!skipOver(s1, "Ha"));
|
||||
assert(s1 == "Hello world");
|
||||
assert(skipOver(s1, "Hell") && s1 == "o world", s1);
|
||||
|
||||
string[] r1 = ["abc", "def", "hij"];
|
||||
dstring[] r2 = ["abc"d];
|
||||
assert(!skipOver!((a, b) => a.equal(b))(r1, ["def"d]), r1[0]);
|
||||
assert(r1 == ["abc", "def", "hij"]);
|
||||
assert(skipOver!((a, b) => a.equal(b))(r1, r2));
|
||||
assert(r1 == ["def", "hij"]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.ascii : isWhite;
|
||||
import std.range.primitives : empty;
|
||||
|
||||
auto s2 = "\t\tvalue";
|
||||
auto s3 = "";
|
||||
auto s4 = "\t\t\t";
|
||||
assert(s2.skipOver!isWhite && s2 == "value");
|
||||
assert(!s3.skipOver!isWhite);
|
||||
assert(s4.skipOver!isWhite && s3.empty);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
auto s = "Hello world";
|
||||
assert(!skipOver(s, "hello", "HellO"));
|
||||
assert(s == "Hello world");
|
||||
|
||||
// the range is skipped over the longest matching needle is skipped
|
||||
assert(skipOver(s, "foo", "hell", "Hello "));
|
||||
assert(s == "world");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
auto s1 = "Hello world";
|
||||
assert(!skipOver(s1, 'a'));
|
||||
assert(s1 == "Hello world");
|
||||
assert(skipOver(s1, 'H') && s1 == "ello world");
|
||||
|
||||
string[] r = ["abc", "def", "hij"];
|
||||
dstring e = "abc"d;
|
||||
assert(!skipOver!((a, b) => a.equal(b))(r, "def"d));
|
||||
assert(r == ["abc", "def", "hij"]);
|
||||
assert(skipOver!((a, b) => a.equal(b))(r, e));
|
||||
assert(r == ["def", "hij"]);
|
||||
|
||||
auto s2 = "";
|
||||
assert(!s2.skipOver('a'));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.ascii : isWhite;
|
||||
import std.range.primitives : empty;
|
||||
|
||||
alias whitespaceSkiper = skipOver!isWhite;
|
||||
|
||||
auto s2 = "\t\tvalue";
|
||||
auto s3 = "";
|
||||
auto s4 = "\t\t\t";
|
||||
assert(whitespaceSkiper(s2) && s2 == "value");
|
||||
assert(!whitespaceSkiper(s2));
|
||||
assert(whitespaceSkiper(s4) && s3.empty);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.ascii : isAlpha;
|
||||
|
||||
assert("abc".startsWith!(a => a.isAlpha));
|
||||
assert("abc".startsWith!isAlpha);
|
||||
assert(!"1ab".startsWith!(a => a.isAlpha));
|
||||
assert(!"".startsWith!(a => a.isAlpha));
|
||||
|
||||
import std.algorithm.comparison : among;
|
||||
assert("abc".startsWith!(a => a.among('a', 'b') != 0));
|
||||
assert(!"abc".startsWith!(a => a.among('b', 'c') != 0));
|
||||
|
||||
assert(startsWith("abc", ""));
|
||||
assert(startsWith("abc", "a"));
|
||||
assert(!startsWith("abc", "b"));
|
||||
assert(startsWith("abc", 'a', "b") == 1);
|
||||
assert(startsWith("abc", "b", "a") == 2);
|
||||
assert(startsWith("abc", "a", "a") == 1);
|
||||
assert(startsWith("abc", "ab", "a") == 2);
|
||||
assert(startsWith("abc", "x", "a", "b") == 2);
|
||||
assert(startsWith("abc", "x", "aa", "ab") == 3);
|
||||
assert(startsWith("abc", "x", "aaa", "sab") == 0);
|
||||
assert(startsWith("abc", "x", "aaa", "a", "sab") == 3);
|
||||
|
||||
import std.typecons : Tuple;
|
||||
alias C = Tuple!(int, "x", int, "y");
|
||||
assert(startsWith!"a.x == b"([ C(1,1), C(1,2), C(2,2) ], [1, 1]));
|
||||
assert(startsWith!"a.x == b"([ C(1,1), C(2,1), C(2,2) ], [1, 1], [1, 2], [1, 3]) == 2);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.searching;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.typecons : No;
|
||||
int[] a = [ 1, 2, 4, 7, 7, 2, 4, 7, 3, 5];
|
||||
assert(equal(a.until(7), [1, 2, 4]));
|
||||
assert(equal(a.until(7, No.openRight), [1, 2, 4, 7]));
|
||||
}
|
||||
|
281
libphobos/testsuite/libphobos.phobos/std_algorithm_setops.d
Normal file
281
libphobos/testsuite/libphobos.phobos/std_algorithm_setops.d
Normal file
|
@ -0,0 +1,281 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.algorithm.searching : canFind;
|
||||
import std.range;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto N = sequence!"n"(0); // the range of natural numbers
|
||||
auto N2 = cartesianProduct(N, N); // the range of all pairs of natural numbers
|
||||
|
||||
// Various arbitrary number pairs can be found in the range in finite time.
|
||||
assert(canFind(N2, tuple(0, 0)));
|
||||
assert(canFind(N2, tuple(123, 321)));
|
||||
assert(canFind(N2, tuple(11, 35)));
|
||||
assert(canFind(N2, tuple(279, 172)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.algorithm.searching : canFind;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto B = [ 1, 2, 3 ];
|
||||
auto C = [ 4, 5, 6 ];
|
||||
auto BC = cartesianProduct(B, C);
|
||||
|
||||
foreach (n; [[1, 4], [2, 4], [3, 4], [1, 5], [2, 5], [3, 5], [1, 6],
|
||||
[2, 6], [3, 6]])
|
||||
{
|
||||
assert(canFind(BC, tuple(n[0], n[1])));
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto A = [ 1, 2, 3 ];
|
||||
auto B = [ 'a', 'b', 'c' ];
|
||||
auto C = [ "x", "y", "z" ];
|
||||
auto ABC = cartesianProduct(A, B, C);
|
||||
|
||||
assert(ABC.equal([
|
||||
tuple(1, 'a', "x"), tuple(1, 'a', "y"), tuple(1, 'a', "z"),
|
||||
tuple(1, 'b', "x"), tuple(1, 'b', "y"), tuple(1, 'b', "z"),
|
||||
tuple(1, 'c', "x"), tuple(1, 'c', "y"), tuple(1, 'c', "z"),
|
||||
tuple(2, 'a', "x"), tuple(2, 'a', "y"), tuple(2, 'a', "z"),
|
||||
tuple(2, 'b', "x"), tuple(2, 'b', "y"), tuple(2, 'b', "z"),
|
||||
tuple(2, 'c', "x"), tuple(2, 'c', "y"), tuple(2, 'c', "z"),
|
||||
tuple(3, 'a', "x"), tuple(3, 'a', "y"), tuple(3, 'a', "z"),
|
||||
tuple(3, 'b', "x"), tuple(3, 'b', "y"), tuple(3, 'b', "z"),
|
||||
tuple(3, 'c', "x"), tuple(3, 'c', "y"), tuple(3, 'c', "z")
|
||||
]));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
// Figure which number can be found in most arrays of the set of
|
||||
// arrays below.
|
||||
double[][] a =
|
||||
[
|
||||
[ 1, 4, 7, 8 ],
|
||||
[ 1, 7 ],
|
||||
[ 1, 7, 8],
|
||||
[ 4 ],
|
||||
[ 7 ],
|
||||
];
|
||||
auto b = new Tuple!(double, uint)[1];
|
||||
// it will modify the input range, hence we need to create a duplicate
|
||||
largestPartialIntersection(a.dup, b);
|
||||
// First member is the item, second is the occurrence count
|
||||
assert(b[0] == tuple(7.0, 4u));
|
||||
// 7.0 occurs in 4 out of 5 inputs, more than any other number
|
||||
|
||||
// If more of the top-frequent numbers are needed, just create a larger
|
||||
// tgt range
|
||||
auto c = new Tuple!(double, uint)[2];
|
||||
largestPartialIntersection(a, c);
|
||||
assert(c[0] == tuple(1.0, 3u));
|
||||
// 1.0 occurs in 3 inputs
|
||||
|
||||
// multiset
|
||||
double[][] x =
|
||||
[
|
||||
[1, 1, 1, 1, 4, 7, 8],
|
||||
[1, 7],
|
||||
[1, 7, 8],
|
||||
[4, 7],
|
||||
[7]
|
||||
];
|
||||
auto y = new Tuple!(double, uint)[2];
|
||||
largestPartialIntersection(x.dup, y);
|
||||
// 7.0 occurs 5 times
|
||||
assert(y[0] == tuple(7.0, 5u));
|
||||
// 1.0 occurs 6 times
|
||||
assert(y[1] == tuple(1.0, 6u));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
// Figure which number can be found in most arrays of the set of
|
||||
// arrays below, with specific per-element weights
|
||||
double[][] a =
|
||||
[
|
||||
[ 1, 4, 7, 8 ],
|
||||
[ 1, 7 ],
|
||||
[ 1, 7, 8],
|
||||
[ 4 ],
|
||||
[ 7 ],
|
||||
];
|
||||
auto b = new Tuple!(double, uint)[1];
|
||||
double[double] weights = [ 1:1.2, 4:2.3, 7:1.1, 8:1.1 ];
|
||||
largestPartialIntersectionWeighted(a, b, weights);
|
||||
// First member is the item, second is the occurrence count
|
||||
assert(b[0] == tuple(4.0, 2u));
|
||||
// 4.0 occurs 2 times -> 4.6 (2 * 2.3)
|
||||
// 7.0 occurs 3 times -> 4.4 (3 * 1.1)
|
||||
|
||||
// multiset
|
||||
double[][] x =
|
||||
[
|
||||
[ 1, 1, 1, 4, 7, 8 ],
|
||||
[ 1, 7 ],
|
||||
[ 1, 7, 8],
|
||||
[ 4 ],
|
||||
[ 7 ],
|
||||
];
|
||||
auto y = new Tuple!(double, uint)[1];
|
||||
largestPartialIntersectionWeighted(x, y, weights);
|
||||
assert(y[0] == tuple(1.0, 5u));
|
||||
// 1.0 occurs 5 times -> 1.2 * 5 = 6
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
double[][] a =
|
||||
[
|
||||
[ 1, 4, 7, 8 ],
|
||||
[ 1, 7 ],
|
||||
[ 1, 7, 8],
|
||||
[ 4 ],
|
||||
[ 7 ],
|
||||
];
|
||||
auto witness = [
|
||||
1, 1, 1, 4, 4, 7, 7, 7, 7, 8, 8
|
||||
];
|
||||
assert(equal(multiwayMerge(a), witness));
|
||||
|
||||
double[][] b =
|
||||
[
|
||||
// range with duplicates
|
||||
[ 1, 1, 4, 7, 8 ],
|
||||
[ 7 ],
|
||||
[ 1, 7, 8],
|
||||
[ 4 ],
|
||||
[ 7 ],
|
||||
];
|
||||
// duplicates are propagated to the resulting range
|
||||
assert(equal(multiwayMerge(b), witness));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
// sets
|
||||
double[][] a =
|
||||
[
|
||||
[ 1, 4, 7, 8 ],
|
||||
[ 1, 7 ],
|
||||
[ 1, 7, 8],
|
||||
[ 4 ],
|
||||
[ 7 ],
|
||||
];
|
||||
|
||||
auto witness = [1, 4, 7, 8];
|
||||
assert(equal(multiwayUnion(a), witness));
|
||||
|
||||
// multisets
|
||||
double[][] b =
|
||||
[
|
||||
[ 1, 1, 1, 4, 7, 8 ],
|
||||
[ 1, 7 ],
|
||||
[ 1, 7, 7, 8],
|
||||
[ 4 ],
|
||||
[ 7 ],
|
||||
];
|
||||
assert(equal(multiwayUnion(b), witness));
|
||||
|
||||
double[][] c =
|
||||
[
|
||||
[9, 8, 8, 8, 7, 6],
|
||||
[9, 8, 6],
|
||||
[9, 8, 5]
|
||||
];
|
||||
auto witness2 = [9, 8, 7, 6, 5];
|
||||
assert(equal(multiwayUnion!"a > b"(c), witness2));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range.primitives : isForwardRange;
|
||||
|
||||
//sets
|
||||
int[] a = [ 1, 2, 4, 5, 7, 9 ];
|
||||
int[] b = [ 0, 1, 2, 4, 7, 8 ];
|
||||
assert(equal(setDifference(a, b), [5, 9]));
|
||||
static assert(isForwardRange!(typeof(setDifference(a, b))));
|
||||
|
||||
// multisets
|
||||
int[] x = [1, 1, 1, 2, 3];
|
||||
int[] y = [1, 1, 2, 4, 5];
|
||||
auto r = setDifference(x, y);
|
||||
assert(equal(r, [1, 3]));
|
||||
assert(setDifference(r, x).empty);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
// sets
|
||||
int[] a = [ 1, 2, 4, 5, 7, 9 ];
|
||||
int[] b = [ 0, 1, 2, 4, 7, 8 ];
|
||||
int[] c = [ 0, 1, 4, 5, 7, 8 ];
|
||||
assert(equal(setIntersection(a, a), a));
|
||||
assert(equal(setIntersection(a, b), [1, 2, 4, 7]));
|
||||
assert(equal(setIntersection(a, b, c), [1, 4, 7]));
|
||||
|
||||
// multisets
|
||||
int[] d = [ 1, 1, 2, 2, 7, 7 ];
|
||||
int[] e = [ 1, 1, 1, 7];
|
||||
assert(equal(setIntersection(a, d), [1, 2, 7]));
|
||||
assert(equal(setIntersection(d, e), [1, 1, 7]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.setops;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range.primitives : isForwardRange;
|
||||
|
||||
// sets
|
||||
int[] a = [ 1, 2, 4, 5, 7, 9 ];
|
||||
int[] b = [ 0, 1, 2, 4, 7, 8 ];
|
||||
assert(equal(setSymmetricDifference(a, b), [0, 5, 8, 9][]));
|
||||
static assert(isForwardRange!(typeof(setSymmetricDifference(a, b))));
|
||||
|
||||
//mutisets
|
||||
int[] c = [1, 1, 1, 1, 2, 2, 2, 4, 5, 6];
|
||||
int[] d = [1, 1, 2, 2, 2, 2, 4, 7, 9];
|
||||
assert(equal(setSymmetricDifference(c, d), setSymmetricDifference(d, c)));
|
||||
assert(equal(setSymmetricDifference(c, d), [1, 1, 2, 5, 6, 7, 9]));
|
||||
}
|
||||
|
462
libphobos/testsuite/libphobos.phobos/std_algorithm_sorting.d
Normal file
462
libphobos/testsuite/libphobos.phobos/std_algorithm_sorting.d
Normal file
|
@ -0,0 +1,462 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
import std.range : assumeSorted;
|
||||
int[] a = [ 1, 2, 3 ];
|
||||
int[] b = [ 4, 0, 6, 5 ];
|
||||
completeSort(assumeSorted(a), b);
|
||||
assert(a == [ 0, 1, 2 ]);
|
||||
assert(b == [ 3, 4, 5, 6 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
assert([1, 1, 2].isSorted);
|
||||
// strictly monotonic doesn't allow duplicates
|
||||
assert(![1, 1, 2].isStrictlyMonotonic);
|
||||
|
||||
int[] arr = [4, 3, 2, 1];
|
||||
assert(!isSorted(arr));
|
||||
assert(!isStrictlyMonotonic(arr));
|
||||
|
||||
assert(isSorted!"a > b"(arr));
|
||||
assert(isStrictlyMonotonic!"a > b"(arr));
|
||||
|
||||
sort(arr);
|
||||
assert(isSorted(arr));
|
||||
assert(isStrictlyMonotonic(arr));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
assert(ordered(42, 42, 43));
|
||||
assert(!strictlyOrdered(43, 42, 45));
|
||||
assert(ordered(42, 42, 43));
|
||||
assert(!strictlyOrdered(42, 42, 43));
|
||||
assert(!ordered(43, 42, 45));
|
||||
// Ordered lexicographically
|
||||
assert(ordered("Jane", "Jim", "Joe"));
|
||||
assert(strictlyOrdered("Jane", "Jim", "Joe"));
|
||||
// Incidentally also ordered by length decreasing
|
||||
assert(ordered!((a, b) => a.length > b.length)("Jane", "Jim", "Joe"));
|
||||
// ... but not strictly so: "Jim" and "Joe" have the same length
|
||||
assert(!strictlyOrdered!((a, b) => a.length > b.length)("Jane", "Jim", "Joe"));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
import std.algorithm.mutation : SwapStrategy;
|
||||
import std.algorithm.searching : count, find;
|
||||
import std.conv : text;
|
||||
import std.range.primitives : empty;
|
||||
|
||||
auto Arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
|
||||
auto arr = Arr.dup;
|
||||
static bool even(int a) { return (a & 1) == 0; }
|
||||
// Partition arr such that even numbers come first
|
||||
auto r = partition!(even)(arr);
|
||||
// Now arr is separated in evens and odds.
|
||||
// Numbers may have become shuffled due to instability
|
||||
assert(r == arr[5 .. $]);
|
||||
assert(count!(even)(arr[0 .. 5]) == 5);
|
||||
assert(find!(even)(r).empty);
|
||||
|
||||
// Can also specify the predicate as a string.
|
||||
// Use 'a' as the predicate argument name
|
||||
arr[] = Arr[];
|
||||
r = partition!(q{(a & 1) == 0})(arr);
|
||||
assert(r == arr[5 .. $]);
|
||||
|
||||
// Now for a stable partition:
|
||||
arr[] = Arr[];
|
||||
r = partition!(q{(a & 1) == 0}, SwapStrategy.stable)(arr);
|
||||
// Now arr is [2 4 6 8 10 1 3 5 7 9], and r points to 1
|
||||
assert(arr == [2, 4, 6, 8, 10, 1, 3, 5, 7, 9] && r == arr[5 .. $]);
|
||||
|
||||
// In case the predicate needs to hold its own state, use a delegate:
|
||||
arr[] = Arr[];
|
||||
int x = 3;
|
||||
// Put stuff greater than 3 on the left
|
||||
bool fun(int a) { return a > x; }
|
||||
r = partition!(fun, SwapStrategy.semistable)(arr);
|
||||
// Now arr is [4 5 6 7 8 9 10 2 3 1] and r points to 2
|
||||
assert(arr == [4, 5, 6, 7, 8, 9, 10, 2, 3, 1] && r == arr[7 .. $]);
|
||||
}
|
||||
|
||||
@safe nothrow unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
int[] a = [5, 3, 2, 6, 4, 1, 3, 7];
|
||||
size_t pivot = pivotPartition(a, a.length / 2);
|
||||
import std.algorithm.searching : all;
|
||||
assert(a[0 .. pivot].all!(x => x <= a[pivot]));
|
||||
assert(a[pivot .. $].all!(x => x >= a[pivot]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
int[] r = [ 1, 3, 5, 7, 8, 2, 4, ];
|
||||
assert(isPartitioned!"a & 1"(r));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
auto a = [ 8, 3, 4, 1, 4, 7, 4 ];
|
||||
auto pieces = partition3(a, 4);
|
||||
assert(pieces[0] == [ 1, 3 ]);
|
||||
assert(pieces[1] == [ 4, 4, 4 ]);
|
||||
assert(pieces[2] == [ 8, 7 ]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
immutable(int[]) arr = [ 2, 3, 1, 5, 0 ];
|
||||
// index using pointers
|
||||
auto index1 = new immutable(int)*[arr.length];
|
||||
makeIndex!("a < b")(arr, index1);
|
||||
assert(isSorted!("*a < *b")(index1));
|
||||
// index using offsets
|
||||
auto index2 = new size_t[arr.length];
|
||||
makeIndex!("a < b")(arr, index2);
|
||||
assert(isSorted!
|
||||
((size_t a, size_t b){ return arr[a] < arr[b];})
|
||||
(index2));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : retro;
|
||||
|
||||
int[] a = [1, 3, 5];
|
||||
int[] b = [2, 3, 4];
|
||||
|
||||
assert(a.merge(b).equal([1, 2, 3, 3, 4, 5]));
|
||||
assert(a.merge(b).retro.equal([5, 4, 3, 3, 2, 1]));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : retro;
|
||||
import std.traits : CommonType;
|
||||
|
||||
alias S = short;
|
||||
alias I = int;
|
||||
alias D = double;
|
||||
|
||||
S[] a = [1, 2, 3];
|
||||
I[] b = [50, 60];
|
||||
D[] c = [10, 20, 30, 40];
|
||||
|
||||
auto m = merge(a, b, c);
|
||||
|
||||
static assert(is(typeof(m.front) == CommonType!(S, I, D)));
|
||||
|
||||
assert(equal(m, [1, 2, 3, 10, 20, 30, 40, 50, 60]));
|
||||
assert(equal(m.retro, [60, 50, 40, 30, 20, 10, 3, 2, 1]));
|
||||
|
||||
m.popFront();
|
||||
assert(equal(m, [2, 3, 10, 20, 30, 40, 50, 60]));
|
||||
m.popBack();
|
||||
assert(equal(m, [2, 3, 10, 20, 30, 40, 50]));
|
||||
m.popFront();
|
||||
assert(equal(m, [3, 10, 20, 30, 40, 50]));
|
||||
m.popBack();
|
||||
assert(equal(m, [3, 10, 20, 30, 40]));
|
||||
m.popFront();
|
||||
assert(equal(m, [10, 20, 30, 40]));
|
||||
m.popBack();
|
||||
assert(equal(m, [10, 20, 30]));
|
||||
m.popFront();
|
||||
assert(equal(m, [20, 30]));
|
||||
m.popBack();
|
||||
assert(equal(m, [20]));
|
||||
m.popFront();
|
||||
assert(m.empty);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
import std.algorithm.mutation : SwapStrategy;
|
||||
static struct Point { int x, y; }
|
||||
auto pts1 = [ Point(0, 0), Point(5, 5), Point(0, 1), Point(0, 2) ];
|
||||
auto pts2 = [ Point(0, 0), Point(0, 1), Point(0, 2), Point(5, 5) ];
|
||||
multiSort!("a.x < b.x", "a.y < b.y", SwapStrategy.unstable)(pts1);
|
||||
assert(pts1 == pts2);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
int[] array = [ 1, 2, 3, 4 ];
|
||||
|
||||
// sort in descending order
|
||||
array.sort!("a > b");
|
||||
assert(array == [ 4, 3, 2, 1 ]);
|
||||
|
||||
// sort in ascending order
|
||||
array.sort();
|
||||
assert(array == [ 1, 2, 3, 4 ]);
|
||||
|
||||
// sort with reusable comparator and chain
|
||||
alias myComp = (x, y) => x > y;
|
||||
assert(array.sort!(myComp).release == [ 4, 3, 2, 1 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
// Showcase stable sorting
|
||||
import std.algorithm.mutation : SwapStrategy;
|
||||
string[] words = [ "aBc", "a", "abc", "b", "ABC", "c" ];
|
||||
sort!("toUpper(a) < toUpper(b)", SwapStrategy.stable)(words);
|
||||
assert(words == [ "a", "aBc", "abc", "ABC", "b", "c" ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
// Sorting floating-point numbers in presence of NaN
|
||||
double[] numbers = [-0.0, 3.0, -2.0, double.nan, 0.0, -double.nan];
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.math.operations : cmp;
|
||||
import std.math.traits : isIdentical;
|
||||
|
||||
sort!((a, b) => cmp(a, b) < 0)(numbers);
|
||||
|
||||
double[] sorted = [-double.nan, -2.0, -0.0, 0.0, 3.0, double.nan];
|
||||
assert(numbers.equal!isIdentical(sorted));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
import std.algorithm.iteration : map;
|
||||
import std.numeric : entropy;
|
||||
|
||||
auto lowEnt = [ 1.0, 0, 0 ],
|
||||
midEnt = [ 0.1, 0.1, 0.8 ],
|
||||
highEnt = [ 0.31, 0.29, 0.4 ];
|
||||
auto arr = new double[][3];
|
||||
arr[0] = midEnt;
|
||||
arr[1] = lowEnt;
|
||||
arr[2] = highEnt;
|
||||
|
||||
schwartzSort!(entropy, "a > b")(arr);
|
||||
|
||||
assert(arr[0] == highEnt);
|
||||
assert(arr[1] == midEnt);
|
||||
assert(arr[2] == lowEnt);
|
||||
assert(isSorted!("a > b")(map!(entropy)(arr)));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
int[] a = [ 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 ];
|
||||
partialSort(a, 5);
|
||||
assert(a[0 .. 5] == [ 0, 1, 2, 3, 4 ]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
int[] a = [5, 7, 2, 6, 7];
|
||||
int[] b = [2, 1, 5, 6, 7, 3, 0];
|
||||
|
||||
partialSort(a, b);
|
||||
assert(a == [0, 1, 2, 2, 3]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
int[] v = [ 25, 7, 9, 2, 0, 5, 21 ];
|
||||
topN!"a < b"(v, 100);
|
||||
assert(v == [ 25, 7, 9, 2, 0, 5, 21 ]);
|
||||
auto n = 4;
|
||||
topN!((a, b) => a < b)(v, n);
|
||||
assert(v[n] == 9);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
int[] a = [ 5, 7, 2, 6, 7 ];
|
||||
int[] b = [ 2, 1, 5, 6, 7, 3, 0 ];
|
||||
topN(a, b);
|
||||
sort(a);
|
||||
assert(a == [0, 1, 2, 2, 3]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
import std.typecons : Yes;
|
||||
|
||||
int[] a = [ 10, 16, 2, 3, 1, 5, 0 ];
|
||||
int[] b = new int[3];
|
||||
topNCopy(a, b, Yes.sortOutput);
|
||||
assert(b == [ 0, 1, 2 ]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
import std.typecons : Yes;
|
||||
|
||||
// Construct index to top 3 elements using numerical indices:
|
||||
int[] a = [ 10, 2, 7, 5, 8, 1 ];
|
||||
int[] index = new int[3];
|
||||
topNIndex(a, index, Yes.sortOutput);
|
||||
assert(index == [5, 1, 3]); // because a[5]==1, a[1]==2, a[3]==5
|
||||
|
||||
// Construct index to top 3 elements using pointer indices:
|
||||
int*[] ptrIndex = new int*[3];
|
||||
topNIndex(a, ptrIndex, Yes.sortOutput);
|
||||
assert(ptrIndex == [ &a[5], &a[1], &a[3] ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
// Step through all permutations of a sorted array in lexicographic order
|
||||
int[] a = [1,2,3];
|
||||
assert(nextPermutation(a) == true);
|
||||
assert(a == [1,3,2]);
|
||||
assert(nextPermutation(a) == true);
|
||||
assert(a == [2,1,3]);
|
||||
assert(nextPermutation(a) == true);
|
||||
assert(a == [2,3,1]);
|
||||
assert(nextPermutation(a) == true);
|
||||
assert(a == [3,1,2]);
|
||||
assert(nextPermutation(a) == true);
|
||||
assert(a == [3,2,1]);
|
||||
assert(nextPermutation(a) == false);
|
||||
assert(a == [1,2,3]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
// Step through permutations of an array containing duplicate elements:
|
||||
int[] a = [1,1,2];
|
||||
assert(nextPermutation(a) == true);
|
||||
assert(a == [1,2,1]);
|
||||
assert(nextPermutation(a) == true);
|
||||
assert(a == [2,1,1]);
|
||||
assert(nextPermutation(a) == false);
|
||||
assert(a == [1,1,2]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
// Step through even permutations of a sorted array in lexicographic order
|
||||
int[] a = [1,2,3];
|
||||
assert(nextEvenPermutation(a) == true);
|
||||
assert(a == [2,3,1]);
|
||||
assert(nextEvenPermutation(a) == true);
|
||||
assert(a == [3,1,2]);
|
||||
assert(nextEvenPermutation(a) == false);
|
||||
assert(a == [1,2,3]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
import std.math.algebraic : sqrt;
|
||||
|
||||
// Print the 60 vertices of a uniform truncated icosahedron (soccer ball)
|
||||
enum real Phi = (1.0 + sqrt(5.0)) / 2.0; // Golden ratio
|
||||
real[][] seeds = [
|
||||
[0.0, 1.0, 3.0*Phi],
|
||||
[1.0, 2.0+Phi, 2.0*Phi],
|
||||
[Phi, 2.0, Phi^^3]
|
||||
];
|
||||
size_t n;
|
||||
foreach (seed; seeds)
|
||||
{
|
||||
// Loop over even permutations of each seed
|
||||
do
|
||||
{
|
||||
// Loop over all sign changes of each permutation
|
||||
size_t i;
|
||||
do
|
||||
{
|
||||
// Generate all possible sign changes
|
||||
for (i=0; i < seed.length; i++)
|
||||
{
|
||||
if (seed[i] != 0.0)
|
||||
{
|
||||
seed[i] = -seed[i];
|
||||
if (seed[i] < 0.0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
n++;
|
||||
} while (i < seed.length);
|
||||
} while (nextEvenPermutation(seed));
|
||||
}
|
||||
assert(n == 60);
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
auto src = [0, 1, 2, 3, 4, 5, 6];
|
||||
auto rslt = [4, 0, 6, 2, 1, 3, 5];
|
||||
|
||||
src = nthPermutation(src, 2982);
|
||||
assert(src == rslt);
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.algorithm.sorting;
|
||||
|
||||
auto src = [0, 1, 2, 3, 4, 5, 6];
|
||||
auto rslt = [4, 0, 6, 2, 1, 3, 5];
|
||||
|
||||
bool worked = nthPermutationImpl(src, 2982);
|
||||
assert(worked);
|
||||
assert(src == rslt);
|
||||
}
|
||||
|
560
libphobos/testsuite/libphobos.phobos/std_array.d
Normal file
560
libphobos/testsuite/libphobos.phobos/std_array.d
Normal file
|
@ -0,0 +1,560 @@
|
|||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto a = array([1, 2, 3, 4, 5][]);
|
||||
assert(a == [ 1, 2, 3, 4, 5 ]);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
import std.range.primitives : isRandomAccessRange;
|
||||
import std.traits : isAutodecodableString;
|
||||
|
||||
// note that if autodecoding is turned off, `array` will not transcode these.
|
||||
static if (isAutodecodableString!string)
|
||||
assert("Hello D".array == "Hello D"d);
|
||||
else
|
||||
assert("Hello D".array == "Hello D");
|
||||
|
||||
static if (isAutodecodableString!wstring)
|
||||
assert("Hello D"w.array == "Hello D"d);
|
||||
else
|
||||
assert("Hello D"w.array == "Hello D"w);
|
||||
|
||||
static assert(isRandomAccessRange!dstring == true);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
import std.range : repeat, zip;
|
||||
import std.typecons : tuple;
|
||||
import std.range.primitives : autodecodeStrings;
|
||||
auto a = assocArray(zip([0, 1, 2], ["a", "b", "c"])); // aka zipMap
|
||||
static assert(is(typeof(a) == string[int]));
|
||||
assert(a == [0:"a", 1:"b", 2:"c"]);
|
||||
|
||||
auto b = assocArray([ tuple("foo", "bar"), tuple("baz", "quux") ]);
|
||||
static assert(is(typeof(b) == string[string]));
|
||||
assert(b == ["foo":"bar", "baz":"quux"]);
|
||||
|
||||
static if (autodecodeStrings)
|
||||
alias achar = dchar;
|
||||
else
|
||||
alias achar = immutable(char);
|
||||
auto c = assocArray("ABCD", true.repeat);
|
||||
static assert(is(typeof(c) == bool[achar]));
|
||||
bool[achar] expected = ['D':true, 'A':true, 'B':true, 'C':true];
|
||||
assert(c == expected);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
import std.algorithm.sorting : sort;
|
||||
import std.typecons : tuple, Tuple;
|
||||
|
||||
auto aa = ["a": 1, "b": 2, "c": 3];
|
||||
Tuple!(string, int)[] pairs;
|
||||
|
||||
// Iteration over key/value pairs.
|
||||
foreach (pair; aa.byPair)
|
||||
{
|
||||
if (pair.key == "b")
|
||||
pairs ~= tuple("B", pair.value);
|
||||
else
|
||||
pairs ~= pair;
|
||||
}
|
||||
|
||||
// Iteration order is implementation-dependent, so we should sort it to get
|
||||
// a fixed order.
|
||||
pairs.sort();
|
||||
assert(pairs == [
|
||||
tuple("B", 2),
|
||||
tuple("a", 1),
|
||||
tuple("c", 3)
|
||||
]);
|
||||
}
|
||||
|
||||
@system nothrow pure unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
double[] arr = uninitializedArray!(double[])(100);
|
||||
assert(arr.length == 100);
|
||||
|
||||
double[][] matrix = uninitializedArray!(double[][])(42, 31);
|
||||
assert(matrix.length == 42);
|
||||
assert(matrix[0].length == 31);
|
||||
|
||||
char*[] ptrs = uninitializedArray!(char*[])(100);
|
||||
assert(ptrs.length == 100);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : repeat;
|
||||
|
||||
auto arr = minimallyInitializedArray!(int[])(42);
|
||||
assert(arr.length == 42);
|
||||
|
||||
// Elements aren't necessarily initialized to 0, so don't do this:
|
||||
// assert(arr.equal(0.repeat(42)));
|
||||
// If that is needed, initialize the array normally instead:
|
||||
auto arr2 = new int[42];
|
||||
assert(arr2.equal(0.repeat(42)));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
int[] a = [ 10, 11, 12, 13, 14 ];
|
||||
int[] b = a[1 .. 3];
|
||||
assert(overlap(a, b) == [ 11, 12 ]);
|
||||
b = b.dup;
|
||||
// overlap disappears even though the content is the same
|
||||
assert(overlap(a, b).empty);
|
||||
|
||||
static test()() @nogc
|
||||
{
|
||||
auto a = "It's three o'clock"d;
|
||||
auto b = a[5 .. 10];
|
||||
return b.overlap(a);
|
||||
}
|
||||
|
||||
//works at compile-time
|
||||
static assert(test == "three"d);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
import std.meta : AliasSeq;
|
||||
|
||||
// can be used as an alternative implementation of overlap that returns
|
||||
// `true` or `false` instead of a slice of the overlap
|
||||
bool isSliceOf(T)(const scope T[] part, const scope T[] whole)
|
||||
{
|
||||
return part.overlap(whole) is part;
|
||||
}
|
||||
|
||||
auto x = [1, 2, 3, 4, 5];
|
||||
|
||||
assert(isSliceOf(x[3..$], x));
|
||||
assert(isSliceOf(x[], x));
|
||||
assert(!isSliceOf(x, x[3..$]));
|
||||
assert(!isSliceOf([7, 8], x));
|
||||
assert(isSliceOf(null, x));
|
||||
|
||||
// null is a slice of itself
|
||||
assert(isSliceOf(null, null));
|
||||
|
||||
foreach (T; AliasSeq!(int[], const(int)[], immutable(int)[], const int[], immutable int[]))
|
||||
{
|
||||
T a = [1, 2, 3, 4, 5];
|
||||
T b = a;
|
||||
T c = a[1 .. $];
|
||||
T d = a[0 .. 1];
|
||||
T e = null;
|
||||
|
||||
assert(isSliceOf(a, a));
|
||||
assert(isSliceOf(b, a));
|
||||
assert(isSliceOf(a, b));
|
||||
|
||||
assert(isSliceOf(c, a));
|
||||
assert(isSliceOf(c, b));
|
||||
assert(!isSliceOf(a, c));
|
||||
assert(!isSliceOf(b, c));
|
||||
|
||||
assert(isSliceOf(d, a));
|
||||
assert(isSliceOf(d, b));
|
||||
assert(!isSliceOf(a, d));
|
||||
assert(!isSliceOf(b, d));
|
||||
|
||||
assert(isSliceOf(e, a));
|
||||
assert(isSliceOf(e, b));
|
||||
assert(isSliceOf(e, c));
|
||||
assert(isSliceOf(e, d));
|
||||
|
||||
//verifies R-value compatibilty
|
||||
assert(!isSliceOf(a[$ .. $], a));
|
||||
assert(isSliceOf(a[0 .. 0], a));
|
||||
assert(isSliceOf(a, a[0.. $]));
|
||||
assert(isSliceOf(a[0 .. $], a));
|
||||
}
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
int[] a = [ 1, 2, 3, 4 ];
|
||||
a.insertInPlace(2, [ 1, 2 ]);
|
||||
assert(a == [ 1, 2, 1, 2, 3, 4 ]);
|
||||
a.insertInPlace(3, 10u, 11);
|
||||
assert(a == [ 1, 2, 1, 10, 11, 2, 3, 4]);
|
||||
|
||||
union U
|
||||
{
|
||||
float a = 3.0;
|
||||
int b;
|
||||
}
|
||||
|
||||
U u1 = { b : 3 };
|
||||
U u2 = { b : 4 };
|
||||
U u3 = { b : 5 };
|
||||
U[] unionArr = [u2, u3];
|
||||
unionArr.insertInPlace(2, [u1]);
|
||||
assert(unionArr == [u2, u3, u1]);
|
||||
unionArr.insertInPlace(0, [u3, u2]);
|
||||
assert(unionArr == [u3, u2, u2, u3, u1]);
|
||||
|
||||
static class C
|
||||
{
|
||||
int a;
|
||||
float b;
|
||||
|
||||
this(int a, float b) { this.a = a; this.b = b; }
|
||||
}
|
||||
|
||||
C c1 = new C(42, 1.0);
|
||||
C c2 = new C(0, 0.0);
|
||||
C c3 = new C(int.max, float.init);
|
||||
|
||||
C[] classArr = [c1, c2, c3];
|
||||
insertInPlace(classArr, 3, [c2, c3]);
|
||||
C[5] classArr1 = classArr;
|
||||
assert(classArr1 == [c1, c2, c3, c2, c3]);
|
||||
insertInPlace(classArr, 0, c3, c1);
|
||||
C[7] classArr2 = classArr;
|
||||
assert(classArr2 == [c3, c1, c1, c2, c3, c2, c3]);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto a = [1, 2, 3, 4, 5];
|
||||
auto b = a[0 .. 2];
|
||||
|
||||
assert(a.sameHead(b));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto a = [1, 2, 3, 4, 5];
|
||||
auto b = a[3..$];
|
||||
|
||||
assert(a.sameTail(b));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto a = "abc";
|
||||
auto s = replicate(a, 3);
|
||||
|
||||
assert(s == "abcabcabc");
|
||||
|
||||
auto b = [1, 2, 3];
|
||||
auto c = replicate(b, 3);
|
||||
|
||||
assert(c == [1, 2, 3, 1, 2, 3, 1, 2, 3]);
|
||||
|
||||
auto d = replicate(b, 0);
|
||||
|
||||
assert(d == []);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
import std.uni : isWhite;
|
||||
assert("Learning,D,is,fun".split(",") == ["Learning", "D", "is", "fun"]);
|
||||
assert("Learning D is fun".split!isWhite == ["Learning", "D", "is", "fun"]);
|
||||
assert("Learning D is fun".split(" D ") == ["Learning", "is fun"]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
string str = "Hello World!";
|
||||
assert(str.split == ["Hello", "World!"]);
|
||||
|
||||
string str2 = "Hello\t\tWorld\t!";
|
||||
assert(str2.split == ["Hello", "World", "!"]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
assert(split("hello world") == ["hello","world"]);
|
||||
assert(split("192.168.0.1", ".") == ["192", "168", "0", "1"]);
|
||||
|
||||
auto a = split([1, 2, 3, 4, 5, 1, 2, 3, 4, 5], [2, 3]);
|
||||
assert(a == [[1], [4, 5, 1], [4, 5]]);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
assert(join(["hello", "silly", "world"], " ") == "hello silly world");
|
||||
assert(join(["hello", "silly", "world"]) == "hellosillyworld");
|
||||
|
||||
assert(join([[1, 2, 3], [4, 5]], [72, 73]) == [1, 2, 3, 72, 73, 4, 5]);
|
||||
assert(join([[1, 2, 3], [4, 5]]) == [1, 2, 3, 4, 5]);
|
||||
|
||||
const string[] arr = ["apple", "banana"];
|
||||
assert(arr.join(",") == "apple,banana");
|
||||
assert(arr.join() == "applebanana");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
assert("Hello Wörld".replace("o Wö", "o Wo") == "Hello World");
|
||||
assert("Hello Wörld".replace("l", "h") == "Hehho Wörhd");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
size_t changed = 0;
|
||||
assert("Hello Wörld".replace("o Wö", "o Wo", changed) == "Hello World");
|
||||
assert(changed == 1);
|
||||
|
||||
changed = 0;
|
||||
assert("Hello Wörld".replace("l", "h", changed) == "Hehho Wörhd");
|
||||
import std.stdio : writeln;
|
||||
writeln(changed);
|
||||
assert(changed == 3);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto arr = [1, 2, 3, 4, 5];
|
||||
auto from = [2, 3];
|
||||
auto to = [4, 6];
|
||||
auto sink = appender!(int[])();
|
||||
|
||||
replaceInto(sink, arr, from, to);
|
||||
|
||||
assert(sink.data == [1, 4, 6, 4, 5]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto arr = [1, 2, 3, 4, 5];
|
||||
auto from = [2, 3];
|
||||
auto to = [4, 6];
|
||||
auto sink = appender!(int[])();
|
||||
|
||||
size_t changed = 0;
|
||||
replaceInto(sink, arr, from, to, changed);
|
||||
|
||||
assert(sink.data == [1, 4, 6, 4, 5]);
|
||||
assert(changed == 1);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto a = [ 1, 2, 3, 4 ];
|
||||
auto b = a.replace(1, 3, [ 9, 9, 9 ]);
|
||||
assert(a == [ 1, 2, 3, 4 ]);
|
||||
assert(b == [ 1, 9, 9, 9, 4 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
int[] a = [1, 4, 5];
|
||||
replaceInPlace(a, 1u, 2u, [2, 3, 4]);
|
||||
assert(a == [1, 2, 3, 4, 5]);
|
||||
replaceInPlace(a, 1u, 2u, cast(int[])[]);
|
||||
assert(a == [1, 3, 4, 5]);
|
||||
replaceInPlace(a, 1u, 3u, a[2 .. 4]);
|
||||
assert(a == [1, 4, 5, 5]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto a = [1, 2, 2, 3, 4, 5];
|
||||
auto b = a.replaceFirst([2], [1337]);
|
||||
assert(b == [1, 1337, 2, 3, 4, 5]);
|
||||
|
||||
auto s = "This is a foo foo list";
|
||||
auto r = s.replaceFirst("foo", "silly");
|
||||
assert(r == "This is a silly foo list");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto a = [1, 2, 2, 3, 4, 5];
|
||||
auto b = a.replaceLast([2], [1337]);
|
||||
assert(b == [1, 2, 1337, 3, 4, 5]);
|
||||
|
||||
auto s = "This is a foo foo list";
|
||||
auto r = s.replaceLast("foo", "silly");
|
||||
assert(r == "This is a foo silly list", r);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto a = [1, 2, 3, 4, 5];
|
||||
auto b = replaceSlice(a, a[1 .. 4], [0, 0, 0]);
|
||||
|
||||
assert(b == [1, 0, 0, 0, 5]);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto app = appender!string();
|
||||
string b = "abcdefg";
|
||||
foreach (char c; b)
|
||||
app.put(c);
|
||||
assert(app[] == "abcdefg");
|
||||
|
||||
int[] a = [ 1, 2 ];
|
||||
auto app2 = appender(a);
|
||||
app2.put(3);
|
||||
assert(app2.length == 3);
|
||||
app2.put([ 4, 5, 6 ]);
|
||||
assert(app2[] == [ 1, 2, 3, 4, 5, 6 ]);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
int[] a = [1, 2];
|
||||
auto app2 = appender(&a);
|
||||
assert(app2[] == [1, 2]);
|
||||
assert(a == [1, 2]);
|
||||
app2 ~= 3;
|
||||
assert(app2.length == 3);
|
||||
app2 ~= [4, 5, 6];
|
||||
assert(app2[] == [1, 2, 3, 4, 5, 6]);
|
||||
assert(a == [1, 2, 3, 4, 5, 6]);
|
||||
|
||||
app2.reserve(5);
|
||||
assert(app2.capacity >= 5);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto w = appender!string;
|
||||
// pre-allocate space for at least 10 elements (this avoids costly reallocations)
|
||||
w.reserve(10);
|
||||
assert(w.capacity >= 10);
|
||||
|
||||
w.put('a'); // single elements
|
||||
w.put("bc"); // multiple elements
|
||||
|
||||
// use the append syntax
|
||||
w ~= 'd';
|
||||
w ~= "ef";
|
||||
|
||||
assert(w[] == "abcdef");
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
int[] a = [1, 2];
|
||||
auto app2 = appender(&a);
|
||||
assert(app2[] == [1, 2]);
|
||||
assert(a == [1, 2]);
|
||||
app2 ~= 3;
|
||||
app2 ~= [4, 5, 6];
|
||||
assert(app2[] == [1, 2, 3, 4, 5, 6]);
|
||||
assert(a == [1, 2, 3, 4, 5, 6]);
|
||||
|
||||
app2.reserve(5);
|
||||
assert(app2.capacity >= 5);
|
||||
}
|
||||
|
||||
nothrow pure @safe @nogc unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto a = [0, 1].staticArray;
|
||||
static assert(is(typeof(a) == int[2]));
|
||||
assert(a == [0, 1]);
|
||||
}
|
||||
|
||||
nothrow pure @safe @nogc unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
auto b = [0, 1].staticArray!long;
|
||||
static assert(is(typeof(b) == long[2]));
|
||||
assert(b == [0, 1]);
|
||||
}
|
||||
|
||||
nothrow pure @safe @nogc unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
import std.range : iota;
|
||||
|
||||
auto input = 3.iota;
|
||||
auto a = input.staticArray!2;
|
||||
static assert(is(typeof(a) == int[2]));
|
||||
assert(a == [0, 1]);
|
||||
auto b = input.staticArray!(long[4]);
|
||||
static assert(is(typeof(b) == long[4]));
|
||||
assert(b == [0, 1, 2, 0]);
|
||||
}
|
||||
|
||||
nothrow pure @safe @nogc unittest
|
||||
{
|
||||
import std.array;
|
||||
|
||||
import std.range : iota;
|
||||
|
||||
enum a = staticArray!(2.iota);
|
||||
static assert(is(typeof(a) == int[2]));
|
||||
assert(a == [0, 1]);
|
||||
|
||||
enum b = staticArray!(long, 2.iota);
|
||||
static assert(is(typeof(b) == long[2]));
|
||||
assert(b == [0, 1]);
|
||||
}
|
||||
|
262
libphobos/testsuite/libphobos.phobos/std_ascii.d
Normal file
262
libphobos/testsuite/libphobos.phobos/std_ascii.d
Normal file
|
@ -0,0 +1,262 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
import std.conv : to;
|
||||
|
||||
assert(42.to!string(16, LetterCase.upper) == "2A");
|
||||
assert(42.to!string(16, LetterCase.lower) == "2a");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
import std.digest.hmac : hmac;
|
||||
import std.digest : toHexString;
|
||||
import std.digest.sha : SHA1;
|
||||
import std.string : representation;
|
||||
|
||||
const sha1HMAC = "A very long phrase".representation
|
||||
.hmac!SHA1("secret".representation)
|
||||
.toHexString!(LetterCase.lower);
|
||||
assert(sha1HMAC == "49f2073c7bf58577e8c9ae59fe8cfd37c9ab94e5");
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
import std.algorithm.comparison, std.algorithm.searching, std.range, std.traits;
|
||||
|
||||
// Because all ASCII characters fit in char, so do these
|
||||
static assert(ControlChar.ack.sizeof == 1);
|
||||
|
||||
// All control characters except del are in row starting from 0
|
||||
static assert(EnumMembers!ControlChar.only.until(ControlChar.del).equal(iota(32)));
|
||||
|
||||
static assert(ControlChar.nul == '\0');
|
||||
static assert(ControlChar.bel == '\a');
|
||||
static assert(ControlChar.bs == '\b');
|
||||
static assert(ControlChar.ff == '\f');
|
||||
static assert(ControlChar.lf == '\n');
|
||||
static assert(ControlChar.cr == '\r');
|
||||
static assert(ControlChar.tab == '\t');
|
||||
static assert(ControlChar.vt == '\v');
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
import std.conv;
|
||||
//Control character table can be used in place of hexcodes.
|
||||
with (ControlChar) assert(text("Phobos", us, "Deimos", us, "Tango", rs) == "Phobos\x1FDeimos\x1FTango\x1E");
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isAlphaNum('A'));
|
||||
assert( isAlphaNum('1'));
|
||||
assert(!isAlphaNum('#'));
|
||||
|
||||
// N.B.: does not return true for non-ASCII Unicode alphanumerics:
|
||||
assert(!isAlphaNum('á'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isAlpha('A'));
|
||||
assert(!isAlpha('1'));
|
||||
assert(!isAlpha('#'));
|
||||
|
||||
// N.B.: does not return true for non-ASCII Unicode alphabetic characters:
|
||||
assert(!isAlpha('á'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isLower('a'));
|
||||
assert(!isLower('A'));
|
||||
assert(!isLower('#'));
|
||||
|
||||
// N.B.: does not return true for non-ASCII Unicode lowercase letters
|
||||
assert(!isLower('á'));
|
||||
assert(!isLower('Á'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isUpper('A'));
|
||||
assert(!isUpper('a'));
|
||||
assert(!isUpper('#'));
|
||||
|
||||
// N.B.: does not return true for non-ASCII Unicode uppercase letters
|
||||
assert(!isUpper('á'));
|
||||
assert(!isUpper('Á'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isDigit('3'));
|
||||
assert( isDigit('8'));
|
||||
assert(!isDigit('B'));
|
||||
assert(!isDigit('#'));
|
||||
|
||||
// N.B.: does not return true for non-ASCII Unicode numbers
|
||||
assert(!isDigit('0')); // full-width digit zero (U+FF10)
|
||||
assert(!isDigit('4')); // full-width digit four (U+FF14)
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isOctalDigit('0'));
|
||||
assert( isOctalDigit('7'));
|
||||
assert(!isOctalDigit('8'));
|
||||
assert(!isOctalDigit('A'));
|
||||
assert(!isOctalDigit('#'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isHexDigit('0'));
|
||||
assert( isHexDigit('A'));
|
||||
assert( isHexDigit('f')); // lowercase hex digits are accepted
|
||||
assert(!isHexDigit('g'));
|
||||
assert(!isHexDigit('G'));
|
||||
assert(!isHexDigit('#'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isWhite(' '));
|
||||
assert( isWhite('\t'));
|
||||
assert( isWhite('\n'));
|
||||
assert(!isWhite('1'));
|
||||
assert(!isWhite('a'));
|
||||
assert(!isWhite('#'));
|
||||
|
||||
// N.B.: Does not return true for non-ASCII Unicode whitespace characters.
|
||||
static import std.uni;
|
||||
assert(std.uni.isWhite('\u00A0'));
|
||||
assert(!isWhite('\u00A0')); // std.ascii.isWhite
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isControl('\0'));
|
||||
assert( isControl('\022'));
|
||||
assert( isControl('\n')); // newline is both whitespace and control
|
||||
assert(!isControl(' '));
|
||||
assert(!isControl('1'));
|
||||
assert(!isControl('a'));
|
||||
assert(!isControl('#'));
|
||||
|
||||
// N.B.: non-ASCII Unicode control characters are not recognized:
|
||||
assert(!isControl('\u0080'));
|
||||
assert(!isControl('\u2028'));
|
||||
assert(!isControl('\u2029'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isPunctuation('.'));
|
||||
assert( isPunctuation(','));
|
||||
assert( isPunctuation(':'));
|
||||
assert( isPunctuation('!'));
|
||||
assert( isPunctuation('#'));
|
||||
assert( isPunctuation('~'));
|
||||
assert( isPunctuation('+'));
|
||||
assert( isPunctuation('_'));
|
||||
|
||||
assert(!isPunctuation('1'));
|
||||
assert(!isPunctuation('a'));
|
||||
assert(!isPunctuation(' '));
|
||||
assert(!isPunctuation('\n'));
|
||||
assert(!isPunctuation('\0'));
|
||||
|
||||
// N.B.: Non-ASCII Unicode punctuation characters are not recognized.
|
||||
assert(!isPunctuation('\u2012')); // (U+2012 = en-dash)
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isGraphical('1'));
|
||||
assert( isGraphical('a'));
|
||||
assert( isGraphical('#'));
|
||||
assert(!isGraphical(' ')); // whitespace is not graphical
|
||||
assert(!isGraphical('\n'));
|
||||
assert(!isGraphical('\0'));
|
||||
|
||||
// N.B.: Unicode graphical characters are not regarded as such.
|
||||
assert(!isGraphical('á'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isPrintable(' ')); // whitespace is printable
|
||||
assert( isPrintable('1'));
|
||||
assert( isPrintable('a'));
|
||||
assert( isPrintable('#'));
|
||||
assert(!isPrintable('\0')); // control characters are not printable
|
||||
|
||||
// N.B.: Printable non-ASCII Unicode characters are not recognized.
|
||||
assert(!isPrintable('á'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert( isASCII('a'));
|
||||
assert(!isASCII('á'));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert(toLower('a') == 'a');
|
||||
assert(toLower('A') == 'a');
|
||||
assert(toLower('#') == '#');
|
||||
|
||||
// N.B.: Non-ASCII Unicode uppercase letters are not converted.
|
||||
assert(toLower('Á') == 'Á');
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.ascii;
|
||||
|
||||
assert(toUpper('a') == 'A');
|
||||
assert(toUpper('A') == 'A');
|
||||
assert(toUpper('#') == '#');
|
||||
|
||||
// N.B.: Non-ASCII Unicode lowercase letters are not converted.
|
||||
assert(toUpper('á') == 'á');
|
||||
}
|
||||
|
180
libphobos/testsuite/libphobos.phobos/std_base64.d
Normal file
180
libphobos/testsuite/libphobos.phobos/std_base64.d
Normal file
|
@ -0,0 +1,180 @@
|
|||
pure @safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
ubyte[] data = [0x83, 0xd7, 0x30, 0x7a, 0x01, 0x3f];
|
||||
assert(Base64.encode(data) == "g9cwegE/");
|
||||
assert(Base64.decode("g9cwegE/") == data);
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
ubyte[] data = [0x83, 0xd7, 0x30, 0x7a, 0x01, 0x3f];
|
||||
assert(Base64URL.encode(data) == "g9cwegE_");
|
||||
assert(Base64URL.decode("g9cwegE_") == data);
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
ubyte[] data = [0x83, 0xd7, 0x30, 0x7b, 0xef];
|
||||
assert(Base64URLNoPadding.encode(data) == "g9cwe-8");
|
||||
assert(Base64URLNoPadding.decode("g9cwe-8") == data);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
ubyte[] data = [0x1a, 0x2b, 0x3c, 0x4d, 0x5d, 0x6e];
|
||||
|
||||
// Allocate a buffer large enough to hold the encoded string.
|
||||
auto buf = new char[Base64.encodeLength(data.length)];
|
||||
|
||||
Base64.encode(data, buf);
|
||||
assert(buf == "Gis8TV1u");
|
||||
|
||||
}
|
||||
|
||||
@nogc nothrow @safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
ubyte[6] data = [0x83, 0xd7, 0x30, 0x7a, 0x01, 0x3f];
|
||||
char[32] buffer; // much bigger than necessary
|
||||
|
||||
// Just to be sure...
|
||||
auto encodedLength = Base64.encodeLength(data.length);
|
||||
assert(buffer.length >= encodedLength);
|
||||
|
||||
// encode() returns a slice to the provided buffer.
|
||||
auto encoded = Base64.encode(data[], buffer[]);
|
||||
assert(encoded is buffer[0 .. encodedLength]);
|
||||
assert(encoded == "g9cwegE/");
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
import std.array : appender;
|
||||
|
||||
auto output = appender!string();
|
||||
ubyte[] data = [0x1a, 0x2b, 0x3c, 0x4d, 0x5d, 0x6e];
|
||||
|
||||
// This overload of encode() returns the number of calls to the output
|
||||
// range's put method.
|
||||
assert(Base64.encode(data, output) == 8);
|
||||
assert(output.data == "Gis8TV1u");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
ubyte[] data = [0x1a, 0x2b, 0x3c, 0x4d, 0x5d, 0x6e];
|
||||
assert(Base64.encode(data) == "Gis8TV1u");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
auto encoded = "Gis8TV1u";
|
||||
|
||||
// Allocate a sufficiently large buffer to hold to decoded result.
|
||||
auto buffer = new ubyte[Base64.decodeLength(encoded.length)];
|
||||
|
||||
Base64.decode(encoded, buffer);
|
||||
assert(buffer == [0x1a, 0x2b, 0x3c, 0x4d, 0x5d, 0x6e]);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
auto encoded = "Gis8TV1u";
|
||||
ubyte[32] buffer; // much bigger than necessary
|
||||
|
||||
// Just to be sure...
|
||||
auto decodedLength = Base64.decodeLength(encoded.length);
|
||||
assert(buffer.length >= decodedLength);
|
||||
|
||||
// decode() returns a slice of the given buffer.
|
||||
auto decoded = Base64.decode(encoded, buffer[]);
|
||||
assert(decoded is buffer[0 .. decodedLength]);
|
||||
assert(decoded == [0x1a, 0x2b, 0x3c, 0x4d, 0x5d, 0x6e]);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
struct OutputRange
|
||||
{
|
||||
ubyte[] result;
|
||||
void put(ubyte b) { result ~= b; }
|
||||
}
|
||||
OutputRange output;
|
||||
|
||||
// This overload of decode() returns the number of calls to put().
|
||||
assert(Base64.decode("Gis8TV1u", output) == 6);
|
||||
assert(output.result == [0x1a, 0x2b, 0x3c, 0x4d, 0x5d, 0x6e]);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
auto data = "Gis8TV1u";
|
||||
assert(Base64.decode(data) == [0x1a, 0x2b, 0x3c, 0x4d, 0x5d, 0x6e]);
|
||||
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
string encoded =
|
||||
"VGhvdSBzaGFsdCBuZXZlciBjb250aW51ZSBhZnRlciBhc3NlcnRpbmcgbnVsbA==";
|
||||
|
||||
assert(Base64.decoder(encoded)
|
||||
.equal("Thou shalt never continue after asserting null"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
import std.string : representation;
|
||||
|
||||
// pre-defined: alias Base64 = Base64Impl!('+', '/');
|
||||
ubyte[] emptyArr;
|
||||
assert(Base64.encode(emptyArr) == "");
|
||||
assert(Base64.encode("f".representation) == "Zg==");
|
||||
assert(Base64.encode("foo".representation) == "Zm9v");
|
||||
|
||||
alias Base64Re = Base64Impl!('!', '=', Base64.NoPadding);
|
||||
assert(Base64Re.encode("f".representation) == "Zg");
|
||||
assert(Base64Re.encode("foo".representation) == "Zm9v");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.base64;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
assertThrown!Base64Exception(Base64.decode("ab|c"));
|
||||
}
|
||||
|
465
libphobos/testsuite/libphobos.phobos/std_bigint.d
Normal file
465
libphobos/testsuite/libphobos.phobos/std_bigint.d
Normal file
|
@ -0,0 +1,465 @@
|
|||
pure @safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
ubyte[] magnitude = [1, 2, 3, 4, 5, 6];
|
||||
auto b1 = BigInt(false, magnitude);
|
||||
assert(cast(long) b1 == 0x01_02_03_04_05_06L);
|
||||
auto b2 = BigInt(true, magnitude);
|
||||
assert(cast(long) b2 == -0x01_02_03_04_05_06L);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
ulong data = 1_000_000_000_000;
|
||||
auto bigData = BigInt(data);
|
||||
assert(bigData == BigInt("1_000_000_000_000"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
const(BigInt) b1 = BigInt("1_234_567_890");
|
||||
BigInt b2 = BigInt(b1);
|
||||
assert(b2 == BigInt("1_234_567_890"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto b = BigInt("123");
|
||||
b = 456;
|
||||
assert(b == BigInt("456"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto b1 = BigInt("123");
|
||||
auto b2 = BigInt("456");
|
||||
b2 = b1;
|
||||
assert(b2 == BigInt("123"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto b = BigInt("1_000_000_000");
|
||||
|
||||
b += 12345;
|
||||
assert(b == BigInt("1_000_012_345"));
|
||||
|
||||
b /= 5;
|
||||
assert(b == BigInt("200_002_469"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("123");
|
||||
auto y = BigInt("321");
|
||||
x += y;
|
||||
assert(x == BigInt("444"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("123");
|
||||
auto y = BigInt("456");
|
||||
BigInt z = x * y;
|
||||
assert(z == BigInt("56088"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("123");
|
||||
x *= 300;
|
||||
assert(x == BigInt("36900"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("1_000_000_500");
|
||||
long l = 1_000_000L;
|
||||
ulong ul = 2_000_000UL;
|
||||
int i = 500_000;
|
||||
short s = 30_000;
|
||||
|
||||
assert(is(typeof(x % l) == long) && x % l == 500L);
|
||||
assert(is(typeof(x % ul) == BigInt) && x % ul == BigInt(500));
|
||||
assert(is(typeof(x % i) == int) && x % i == 500);
|
||||
assert(is(typeof(x % s) == int) && x % s == 10500);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("100");
|
||||
BigInt y = 123 + x;
|
||||
assert(y == BigInt("223"));
|
||||
|
||||
BigInt z = 123 - x;
|
||||
assert(z == BigInt("23"));
|
||||
|
||||
// Dividing a built-in integer type by BigInt always results in
|
||||
// something that fits in a built-in type, so the built-in type is
|
||||
// returned, not BigInt.
|
||||
assert(is(typeof(1000 / x) == int));
|
||||
assert(1000 / x == 10);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("1234");
|
||||
assert(-x == BigInt("-1234"));
|
||||
|
||||
++x;
|
||||
assert(x == BigInt("1235"));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
// Note that when comparing a BigInt to a float or double the
|
||||
// full precision of the BigInt is always considered, unlike
|
||||
// when comparing an int to a float or a long to a double.
|
||||
assert(BigInt(123456789) != cast(float) 123456789);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
// Non-zero values are regarded as true
|
||||
auto x = BigInt("1");
|
||||
auto y = BigInt("10");
|
||||
assert(x);
|
||||
assert(y);
|
||||
|
||||
// Zero value is regarded as false
|
||||
auto z = BigInt("0");
|
||||
assert(!z);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
import std.conv : to, ConvOverflowException;
|
||||
import std.exception : assertThrown;
|
||||
|
||||
assert(BigInt("0").to!int == 0);
|
||||
|
||||
assert(BigInt("0").to!ubyte == 0);
|
||||
assert(BigInt("255").to!ubyte == 255);
|
||||
assertThrown!ConvOverflowException(BigInt("256").to!ubyte);
|
||||
assertThrown!ConvOverflowException(BigInt("-1").to!ubyte);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
assert(cast(float) BigInt("35540592535949172786332045140593475584")
|
||||
== 35540592535949172786332045140593475584.0f);
|
||||
assert(cast(double) BigInt("35540601499647381470685035515422441472")
|
||||
== 35540601499647381470685035515422441472.0);
|
||||
assert(cast(real) BigInt("35540601499647381470685035515422441472")
|
||||
== 35540601499647381470685035515422441472.0L);
|
||||
|
||||
assert(cast(float) BigInt("-0x1345_6780_0000_0000_0000_0000_0000") == -0x1.3456_78p+108f );
|
||||
assert(cast(double) BigInt("-0x1345_678a_bcde_f000_0000_0000_0000") == -0x1.3456_78ab_cdefp+108 );
|
||||
assert(cast(real) BigInt("-0x1345_678a_bcde_f000_0000_0000_0000") == -0x1.3456_78ab_cdefp+108L);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
// BigInts whose values cannot be exactly represented as float/double/real
|
||||
// are rounded when cast to float/double/real. When cast to float or
|
||||
// double or 64-bit real the rounding is strictly defined. When cast
|
||||
// to extended-precision real the rounding rules vary by environment.
|
||||
|
||||
// BigInts that fall somewhere between two non-infinite floats/doubles
|
||||
// are rounded to the closer value when cast to float/double.
|
||||
assert(cast(float) BigInt(0x1aaa_aae7) == 0x1.aaa_aaep+28f);
|
||||
assert(cast(float) BigInt(0x1aaa_aaff) == 0x1.aaa_ab0p+28f);
|
||||
assert(cast(float) BigInt(-0x1aaa_aae7) == -0x1.aaaaaep+28f);
|
||||
assert(cast(float) BigInt(-0x1aaa_aaff) == -0x1.aaaab0p+28f);
|
||||
|
||||
assert(cast(double) BigInt(0x1aaa_aaaa_aaaa_aa77) == 0x1.aaa_aaaa_aaaa_aa00p+60);
|
||||
assert(cast(double) BigInt(0x1aaa_aaaa_aaaa_aaff) == 0x1.aaa_aaaa_aaaa_ab00p+60);
|
||||
assert(cast(double) BigInt(-0x1aaa_aaaa_aaaa_aa77) == -0x1.aaa_aaaa_aaaa_aa00p+60);
|
||||
assert(cast(double) BigInt(-0x1aaa_aaaa_aaaa_aaff) == -0x1.aaa_aaaa_aaaa_ab00p+60);
|
||||
|
||||
// BigInts that fall exactly between two non-infinite floats/doubles
|
||||
// are rounded away from zero when cast to float/double. (Note that
|
||||
// in most environments this is NOT the same rounding rule rule used
|
||||
// when casting int/long to float/double.)
|
||||
assert(cast(float) BigInt(0x1aaa_aaf0) == 0x1.aaa_ab0p+28f);
|
||||
assert(cast(float) BigInt(-0x1aaa_aaf0) == -0x1.aaaab0p+28f);
|
||||
|
||||
assert(cast(double) BigInt(0x1aaa_aaaa_aaaa_aa80) == 0x1.aaa_aaaa_aaaa_ab00p+60);
|
||||
assert(cast(double) BigInt(-0x1aaa_aaaa_aaaa_aa80) == -0x1.aaa_aaaa_aaaa_ab00p+60);
|
||||
|
||||
// BigInts that are bounded on one side by the largest positive or
|
||||
// most negative finite float/double and on the other side by infinity
|
||||
// or -infinity are rounded as if in place of infinity was the value
|
||||
// `2^^(T.max_exp)` when cast to float/double.
|
||||
assert(cast(float) BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999") == float.infinity);
|
||||
assert(cast(float) BigInt("-999_999_999_999_999_999_999_999_999_999_999_999_999") == -float.infinity);
|
||||
|
||||
assert(cast(double) BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999") < double.infinity);
|
||||
assert(cast(real) BigInt("999_999_999_999_999_999_999_999_999_999_999_999_999") < real.infinity);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
const(BigInt) x = BigInt("123");
|
||||
BigInt y = cast() x; // cast away const
|
||||
assert(y == x);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("100");
|
||||
auto y = BigInt("10");
|
||||
int z = 50;
|
||||
const int w = 200;
|
||||
|
||||
assert(y < x);
|
||||
assert(x > z);
|
||||
assert(z > y);
|
||||
assert(x < w);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("0x1abc_de80_0000_0000_0000_0000_0000_0000");
|
||||
BigInt y = x - 1;
|
||||
BigInt z = x + 1;
|
||||
|
||||
double d = 0x1.abcde8p124;
|
||||
assert(y < d);
|
||||
assert(z > d);
|
||||
assert(x >= d && x <= d);
|
||||
|
||||
// Note that when comparing a BigInt to a float or double the
|
||||
// full precision of the BigInt is always considered, unlike
|
||||
// when comparing an int to a float or a long to a double.
|
||||
assert(BigInt(123456789) < cast(float) 123456789);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto b = BigInt("12345");
|
||||
long l = b.toLong();
|
||||
assert(l == 12345);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto big = BigInt("5_000_000");
|
||||
auto i = big.toInt();
|
||||
assert(i == 5_000_000);
|
||||
|
||||
// Numbers that are too big to fit into an int will be clamped to int.max.
|
||||
auto tooBig = BigInt("5_000_000_000");
|
||||
i = tooBig.toInt();
|
||||
assert(i == int.max);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
import std.format : format;
|
||||
|
||||
auto x = BigInt("1_000_000");
|
||||
x *= 12345;
|
||||
|
||||
assert(format("%d", x) == "12345000000");
|
||||
assert(format("%x", x) == "2_dfd1c040");
|
||||
assert(format("%X", x) == "2_DFD1C040");
|
||||
assert(format("%o", x) == "133764340100");
|
||||
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
string[BigInt] aa;
|
||||
aa[BigInt(123)] = "abc";
|
||||
aa[BigInt(456)] = "def";
|
||||
|
||||
assert(aa[BigInt(123)] == "abc");
|
||||
assert(aa[BigInt(456)] == "def");
|
||||
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto a = BigInt("1000");
|
||||
assert(a.ulongLength() == 1);
|
||||
assert(a.getDigit(0) == 1000);
|
||||
|
||||
assert(a.uintLength() == 1);
|
||||
assert(a.getDigit!uint(0) == 1000);
|
||||
|
||||
auto b = BigInt("2_000_000_000_000_000_000_000_000_000");
|
||||
assert(b.ulongLength() == 2);
|
||||
assert(b.getDigit(0) == 4584946418820579328);
|
||||
assert(b.getDigit(1) == 108420217);
|
||||
|
||||
assert(b.uintLength() == 3);
|
||||
assert(b.getDigit!uint(0) == 3489660928);
|
||||
assert(b.getDigit!uint(1) == 1067516025);
|
||||
assert(b.getDigit!uint(2) == 108420217);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
BigInt a = "9588669891916142";
|
||||
BigInt b = "7452469135154800";
|
||||
auto c = a * b;
|
||||
assert(c == BigInt("71459266416693160362545788781600"));
|
||||
auto d = b * a;
|
||||
assert(d == BigInt("71459266416693160362545788781600"));
|
||||
assert(d == c);
|
||||
d = c * BigInt("794628672112");
|
||||
assert(d == BigInt("56783581982794522489042432639320434378739200"));
|
||||
auto e = c + d;
|
||||
assert(e == BigInt("56783581982865981755459125799682980167520800"));
|
||||
auto f = d + c;
|
||||
assert(f == e);
|
||||
auto g = f - c;
|
||||
assert(g == d);
|
||||
g = f - d;
|
||||
assert(g == c);
|
||||
e = 12345678;
|
||||
g = c + e;
|
||||
auto h = g / b;
|
||||
auto i = g % b;
|
||||
assert(h == a);
|
||||
assert(i == e);
|
||||
BigInt j = "-0x9A56_57f4_7B83_AB78";
|
||||
BigInt k = j;
|
||||
j ^^= 11;
|
||||
assert(k ^^ 11 == j);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("123");
|
||||
x *= 1000;
|
||||
x += 456;
|
||||
|
||||
auto xstr = x.toDecimalString();
|
||||
assert(xstr == "123456");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto x = BigInt("123");
|
||||
x *= 1000;
|
||||
x += 456;
|
||||
|
||||
auto xstr = x.toHex();
|
||||
assert(xstr == "1E240");
|
||||
}
|
||||
|
||||
nothrow pure @safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
assert((-1).absUnsign == 1);
|
||||
assert(1.absUnsign == 1);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
auto a = BigInt(123);
|
||||
auto b = BigInt(25);
|
||||
BigInt q, r;
|
||||
|
||||
divMod(a, b, q, r);
|
||||
|
||||
assert(q == 4);
|
||||
assert(r == 23);
|
||||
assert(q * b + r == a);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.bigint;
|
||||
|
||||
BigInt base = BigInt("123456789012345678901234567890");
|
||||
BigInt exponent = BigInt("1234567890123456789012345678901234567");
|
||||
BigInt modulus = BigInt("1234567");
|
||||
|
||||
BigInt result = powmod(base, exponent, modulus);
|
||||
assert(result == 359079);
|
||||
}
|
||||
|
1628
libphobos/testsuite/libphobos.phobos/std_bitmanip.d
Normal file
1628
libphobos/testsuite/libphobos.phobos/std_bitmanip.d
Normal file
File diff suppressed because it is too large
Load diff
628
libphobos/testsuite/libphobos.phobos/std_checkedint.d
Normal file
628
libphobos/testsuite/libphobos.phobos/std_checkedint.d
Normal file
|
@ -0,0 +1,628 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
int[] concatAndAdd(int[] a, int[] b, int offset)
|
||||
{
|
||||
// Aborts on overflow on size computation
|
||||
auto r = new int[(checked(a.length) + b.length).get];
|
||||
// Aborts on overflow on element computation
|
||||
foreach (i; 0 .. a.length)
|
||||
r[i] = (a[i] + checked(offset)).get;
|
||||
foreach (i; 0 .. b.length)
|
||||
r[i + a.length] = (b[i] + checked(offset)).get;
|
||||
return r;
|
||||
}
|
||||
assert(concatAndAdd([1, 2, 3], [4, 5], -1) == [0, 1, 2, 3, 4]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x = (cast(byte) 127).checked!Saturate;
|
||||
assert(x == 127);
|
||||
x++;
|
||||
assert(x == 127);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x = 100.checked!WithNaN;
|
||||
assert(x == 100);
|
||||
x /= 0;
|
||||
assert(x.isNaN);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
uint x = 1;
|
||||
auto y = x.checked!ProperCompare;
|
||||
assert(x < -1); // built-in comparison
|
||||
assert(y > -1); // ProperCompare
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
auto x = -1.checked!Throw;
|
||||
assertThrown(x / 0);
|
||||
assertThrown(x + int.min);
|
||||
assertThrown(x == uint.max);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x = checked(ubyte(42));
|
||||
static assert(is(typeof(x.get()) == ubyte));
|
||||
assert(x.get == 42);
|
||||
const y = checked(ubyte(42));
|
||||
static assert(is(typeof(y.get()) == const ubyte));
|
||||
assert(y.get == 42);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
assert(Checked!short.min == -32768);
|
||||
assert(Checked!(short, WithNaN).min == -32767);
|
||||
assert(Checked!(uint, WithNaN).max == uint.max - 1);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto a = checked(42L);
|
||||
assert(a == 42);
|
||||
auto b = Checked!long(4242); // convert 4242 to long
|
||||
assert(b == 4242);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
Checked!long a;
|
||||
a = 42L;
|
||||
assert(a == 42);
|
||||
a = 4242;
|
||||
assert(a == 4242);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
Checked!long a, b;
|
||||
a = b = 3;
|
||||
assert(a == 3 && b == 3);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
import std.conv : to;
|
||||
|
||||
const a = to!long("1234");
|
||||
const b = to!(Checked!long)("1234");
|
||||
assert(a == b);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
assert(cast(uint) checked(42) == 42);
|
||||
assert(cast(uint) checked!WithNaN(-42) == uint.max);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
import std.traits : isUnsigned;
|
||||
|
||||
static struct MyHook
|
||||
{
|
||||
static bool thereWereErrors;
|
||||
static bool hookOpEquals(L, R)(L lhs, R rhs)
|
||||
{
|
||||
if (lhs != rhs) return false;
|
||||
static if (isUnsigned!L && !isUnsigned!R)
|
||||
{
|
||||
if (lhs > 0 && rhs < 0) thereWereErrors = true;
|
||||
}
|
||||
else static if (isUnsigned!R && !isUnsigned!L)
|
||||
if (lhs < 0 && rhs > 0) thereWereErrors = true;
|
||||
// Preserve built-in behavior.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
auto a = checked!MyHook(-42);
|
||||
assert(a == uint(-42));
|
||||
assert(MyHook.thereWereErrors);
|
||||
MyHook.thereWereErrors = false;
|
||||
assert(checked!MyHook(uint(-42)) == -42);
|
||||
assert(MyHook.thereWereErrors);
|
||||
static struct MyHook2
|
||||
{
|
||||
static bool hookOpEquals(L, R)(L lhs, R rhs)
|
||||
{
|
||||
return lhs == rhs;
|
||||
}
|
||||
}
|
||||
MyHook.thereWereErrors = false;
|
||||
assert(checked!MyHook2(uint(-42)) == a);
|
||||
// Hook on left hand side takes precedence, so no errors
|
||||
assert(!MyHook.thereWereErrors);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
import std.format;
|
||||
|
||||
assert(format("%04d", checked(15)) == "0015");
|
||||
assert(format("0x%02x", checked(15)) == "0x0f");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
import std.traits : isUnsigned;
|
||||
|
||||
static struct MyHook
|
||||
{
|
||||
static bool thereWereErrors;
|
||||
static int hookOpCmp(L, R)(L lhs, R rhs)
|
||||
{
|
||||
static if (isUnsigned!L && !isUnsigned!R)
|
||||
{
|
||||
if (rhs < 0 && rhs >= lhs)
|
||||
thereWereErrors = true;
|
||||
}
|
||||
else static if (isUnsigned!R && !isUnsigned!L)
|
||||
{
|
||||
if (lhs < 0 && lhs >= rhs)
|
||||
thereWereErrors = true;
|
||||
}
|
||||
// Preserve built-in behavior.
|
||||
return lhs < rhs ? -1 : lhs > rhs;
|
||||
}
|
||||
}
|
||||
auto a = checked!MyHook(-42);
|
||||
assert(a > uint(42));
|
||||
assert(MyHook.thereWereErrors);
|
||||
static struct MyHook2
|
||||
{
|
||||
static int hookOpCmp(L, R)(L lhs, R rhs)
|
||||
{
|
||||
// Default behavior
|
||||
return lhs < rhs ? -1 : lhs > rhs;
|
||||
}
|
||||
}
|
||||
MyHook.thereWereErrors = false;
|
||||
assert(Checked!(uint, MyHook2)(uint(-42)) <= a);
|
||||
//assert(Checked!(uint, MyHook2)(uint(-42)) >= a);
|
||||
// Hook on left hand side takes precedence, so no errors
|
||||
assert(!MyHook.thereWereErrors);
|
||||
assert(a <= Checked!(uint, MyHook2)(uint(-42)));
|
||||
assert(MyHook.thereWereErrors);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
static struct MyHook
|
||||
{
|
||||
static bool thereWereErrors;
|
||||
static L hookOpUnary(string x, L)(L lhs)
|
||||
{
|
||||
if (x == "-" && lhs == -lhs) thereWereErrors = true;
|
||||
return -lhs;
|
||||
}
|
||||
}
|
||||
auto a = checked!MyHook(long.min);
|
||||
assert(a == -a);
|
||||
assert(MyHook.thereWereErrors);
|
||||
auto b = checked!void(42);
|
||||
assert(++b == 43);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
static struct MyHook
|
||||
{
|
||||
static bool thereWereErrors;
|
||||
static T onLowerBound(Rhs, T)(Rhs rhs, T bound)
|
||||
{
|
||||
thereWereErrors = true;
|
||||
return bound;
|
||||
}
|
||||
static T onUpperBound(Rhs, T)(Rhs rhs, T bound)
|
||||
{
|
||||
thereWereErrors = true;
|
||||
return bound;
|
||||
}
|
||||
}
|
||||
auto x = checked!MyHook(byte.min);
|
||||
x -= 1;
|
||||
assert(MyHook.thereWereErrors);
|
||||
MyHook.thereWereErrors = false;
|
||||
x = byte.max;
|
||||
x += 1;
|
||||
assert(MyHook.thereWereErrors);
|
||||
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
// Hook that ignores all problems.
|
||||
static struct Ignore
|
||||
{
|
||||
@nogc nothrow pure @safe static:
|
||||
Dst onBadCast(Dst, Src)(Src src) { return cast(Dst) src; }
|
||||
Lhs onLowerBound(Rhs, T)(Rhs rhs, T bound) { return cast(T) rhs; }
|
||||
T onUpperBound(Rhs, T)(Rhs rhs, T bound) { return cast(T) rhs; }
|
||||
bool hookOpEquals(Lhs, Rhs)(Lhs lhs, Rhs rhs) { return lhs == rhs; }
|
||||
int hookOpCmp(Lhs, Rhs)(Lhs lhs, Rhs rhs) { return (lhs > rhs) - (lhs < rhs); }
|
||||
typeof(~Lhs()) onOverflow(string x, Lhs)(ref Lhs lhs) { return mixin(x ~ "lhs"); }
|
||||
typeof(Lhs() + Rhs()) onOverflow(string x, Lhs, Rhs)(Lhs lhs, Rhs rhs)
|
||||
{
|
||||
static if (x == "/")
|
||||
return typeof(lhs / rhs).min;
|
||||
else
|
||||
return mixin("lhs" ~ x ~ "rhs");
|
||||
}
|
||||
}
|
||||
|
||||
auto x = Checked!(int, Ignore)(5) + 7;
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
static assert(is(typeof(checked(42)) == Checked!int));
|
||||
assert(checked(42) == Checked!int(42));
|
||||
static assert(is(typeof(checked!WithNaN(42)) == Checked!(int, WithNaN)));
|
||||
assert(checked!WithNaN(42) == Checked!(int, WithNaN)(42));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
void test(T)()
|
||||
{
|
||||
Checked!(int, Abort) x;
|
||||
x = 42;
|
||||
auto x1 = cast(T) x;
|
||||
assert(x1 == 42);
|
||||
//x1 += long(int.max);
|
||||
}
|
||||
test!short;
|
||||
test!(const short);
|
||||
test!(immutable short);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
void test(T)()
|
||||
{
|
||||
Checked!(int, Throw) x;
|
||||
x = 42;
|
||||
auto x1 = cast(T) x;
|
||||
assert(x1 == 42);
|
||||
x = T.max + 1;
|
||||
import std.exception : assertThrown, assertNotThrown;
|
||||
assertThrown(cast(T) x);
|
||||
x = x.max;
|
||||
assertThrown(x += 42);
|
||||
assertThrown(x += 42L);
|
||||
x = x.min;
|
||||
assertThrown(-x);
|
||||
assertThrown(x -= 42);
|
||||
assertThrown(x -= 42L);
|
||||
x = -1;
|
||||
assertNotThrown(x == -1);
|
||||
assertThrown(x == uint(-1));
|
||||
assertNotThrown(x <= -1);
|
||||
assertThrown(x <= uint(-1));
|
||||
}
|
||||
test!short;
|
||||
test!(const short);
|
||||
test!(immutable short);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x = checked!Warn(-42);
|
||||
// Passes
|
||||
assert(x == -42);
|
||||
// Passes but prints a warning
|
||||
// assert(x == uint(-42));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x = checked!Warn(-42);
|
||||
// Passes
|
||||
assert(x <= -42);
|
||||
// Passes but prints a warning
|
||||
// assert(x <= uint(-42));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x = checked!Warn(42);
|
||||
short x1 = cast(short) x;
|
||||
//x += long(int.max);
|
||||
auto y = checked!Warn(cast(const int) 42);
|
||||
short y1 = cast(const byte) y;
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
alias opEqualsProper = ProperCompare.hookOpEquals;
|
||||
assert(opEqualsProper(42, 42));
|
||||
assert(opEqualsProper(42.0, 42.0));
|
||||
assert(opEqualsProper(42u, 42));
|
||||
assert(opEqualsProper(42, 42u));
|
||||
assert(-1 == 4294967295u);
|
||||
assert(!opEqualsProper(-1, 4294967295u));
|
||||
assert(!opEqualsProper(const uint(-1), -1));
|
||||
assert(!opEqualsProper(uint(-1), -1.0));
|
||||
assert(3_000_000_000U == -1_294_967_296);
|
||||
assert(!opEqualsProper(3_000_000_000U, -1_294_967_296));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x = checked!WithNaN(422);
|
||||
assert((cast(ubyte) x) == 255);
|
||||
x = checked!WithNaN(-422);
|
||||
assert((cast(byte) x) == -128);
|
||||
assert(cast(short) x == -422);
|
||||
assert(cast(bool) x);
|
||||
x = x.init; // set back to NaN
|
||||
assert(x != true);
|
||||
assert(x != false);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
Checked!(int, WithNaN) x;
|
||||
assert(!(x < 0) && !(x > 0) && !(x == 0));
|
||||
x = 1;
|
||||
assert(x > 0 && !(x < 0) && !(x == 0));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
Checked!(int, WithNaN) x;
|
||||
++x;
|
||||
assert(x.isNaN);
|
||||
x = 1;
|
||||
assert(!x.isNaN);
|
||||
x = -x;
|
||||
++x;
|
||||
assert(!x.isNaN);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
Checked!(int, WithNaN) x;
|
||||
assert((x + 1).isNaN);
|
||||
x = 100;
|
||||
assert(!(x + 1).isNaN);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
Checked!(int, WithNaN) x;
|
||||
assert((1 + x).isNaN);
|
||||
x = 100;
|
||||
assert(!(1 + x).isNaN);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
Checked!(int, WithNaN) x;
|
||||
x += 4;
|
||||
assert(x.isNaN);
|
||||
x = 0;
|
||||
x += 4;
|
||||
assert(!x.isNaN);
|
||||
x += int.max;
|
||||
assert(x.isNaN);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x1 = Checked!(int, WithNaN)();
|
||||
assert(x1.isNaN);
|
||||
assert(x1.get == int.min);
|
||||
assert(x1 != x1);
|
||||
assert(!(x1 < x1));
|
||||
assert(!(x1 > x1));
|
||||
assert(!(x1 == x1));
|
||||
++x1;
|
||||
assert(x1.isNaN);
|
||||
assert(x1.get == int.min);
|
||||
--x1;
|
||||
assert(x1.isNaN);
|
||||
assert(x1.get == int.min);
|
||||
x1 = 42;
|
||||
assert(!x1.isNaN);
|
||||
assert(x1 == x1);
|
||||
assert(x1 <= x1);
|
||||
assert(x1 >= x1);
|
||||
static assert(x1.min == int.min + 1);
|
||||
x1 += long(int.max);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x1 = Checked!(int, WithNaN)();
|
||||
assert(x1.isNaN);
|
||||
x1 = 1;
|
||||
assert(!x1.isNaN);
|
||||
x1 = x1.init;
|
||||
assert(x1.isNaN);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x = checked!Saturate(short(100));
|
||||
x += 33000;
|
||||
assert(x == short.max);
|
||||
x -= 70000;
|
||||
assert(x == short.min);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
assert(checked!Saturate(int.max) + 1 == int.max);
|
||||
assert(checked!Saturate(100) ^^ 10 == int.max);
|
||||
assert(checked!Saturate(-100) ^^ 10 == int.max);
|
||||
assert(checked!Saturate(100) / 0 == int.max);
|
||||
assert(checked!Saturate(100) << -1 == 0);
|
||||
assert(checked!Saturate(100) << 33 == int.max);
|
||||
assert(checked!Saturate(100) >> -1 == int.max);
|
||||
assert(checked!Saturate(100) >> 33 == 0);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
auto x = checked!Saturate(int.max);
|
||||
++x;
|
||||
assert(x == int.max);
|
||||
--x;
|
||||
assert(x == int.max - 1);
|
||||
x = int.min;
|
||||
assert(-x == int.max);
|
||||
x -= 42;
|
||||
assert(x == int.min);
|
||||
assert(x * -2 == int.max);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
bool overflow;
|
||||
assert(opChecked!"+"(const short(1), short(1), overflow) == 2 && !overflow);
|
||||
assert(opChecked!"+"(1, 1, overflow) == 2 && !overflow);
|
||||
assert(opChecked!"+"(1, 1u, overflow) == 2 && !overflow);
|
||||
assert(opChecked!"+"(-1, 1u, overflow) == 0 && !overflow);
|
||||
assert(opChecked!"+"(1u, -1, overflow) == 0 && !overflow);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
bool overflow;
|
||||
assert(opChecked!"-"(1, 1, overflow) == 0 && !overflow);
|
||||
assert(opChecked!"-"(1, 1u, overflow) == 0 && !overflow);
|
||||
assert(opChecked!"-"(1u, -1, overflow) == 2 && !overflow);
|
||||
assert(opChecked!"-"(-1, 1u, overflow) == 0 && overflow);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.checkedint;
|
||||
|
||||
struct MyHook
|
||||
{
|
||||
static size_t hookToHash(T)(const T payload) nothrow @trusted
|
||||
{
|
||||
return .hashOf(payload);
|
||||
}
|
||||
}
|
||||
|
||||
int[Checked!(int, MyHook)] aa;
|
||||
Checked!(int, MyHook) var = 42;
|
||||
aa[var] = 100;
|
||||
|
||||
assert(aa[var] == 100);
|
||||
|
||||
int[Checked!(int, Abort)] bb;
|
||||
Checked!(int, Abort) var2 = 42;
|
||||
bb[var2] = 100;
|
||||
|
||||
assert(bb[var2] == 100);
|
||||
}
|
||||
|
403
libphobos/testsuite/libphobos.phobos/std_complex.d
Normal file
403
libphobos/testsuite/libphobos.phobos/std_complex.d
Normal file
|
@ -0,0 +1,403 @@
|
|||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
auto a = complex(1.0);
|
||||
static assert(is(typeof(a) == Complex!double));
|
||||
assert(a.re == 1.0);
|
||||
assert(a.im == 0.0);
|
||||
|
||||
auto b = complex(2.0L);
|
||||
static assert(is(typeof(b) == Complex!real));
|
||||
assert(b.re == 2.0L);
|
||||
assert(b.im == 0.0L);
|
||||
|
||||
auto c = complex(1.0, 2.0);
|
||||
static assert(is(typeof(c) == Complex!double));
|
||||
assert(c.re == 1.0);
|
||||
assert(c.im == 2.0);
|
||||
|
||||
auto d = complex(3.0, 4.0L);
|
||||
static assert(is(typeof(d) == Complex!real));
|
||||
assert(d.re == 3.0);
|
||||
assert(d.im == 4.0L);
|
||||
|
||||
auto e = complex(1);
|
||||
static assert(is(typeof(e) == Complex!double));
|
||||
assert(e.re == 1);
|
||||
assert(e.im == 0);
|
||||
|
||||
auto f = complex(1L, 2);
|
||||
static assert(is(typeof(f) == Complex!double));
|
||||
assert(f.re == 1L);
|
||||
assert(f.im == 2);
|
||||
|
||||
auto g = complex(3, 4.0L);
|
||||
static assert(is(typeof(g) == Complex!real));
|
||||
assert(g.re == 3);
|
||||
assert(g.im == 4.0L);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
auto c = complex(1.2, 3.4);
|
||||
|
||||
// Vanilla toString formatting:
|
||||
assert(c.toString() == "1.2+3.4i");
|
||||
|
||||
// Formatting with std.string.format specs: the precision and width
|
||||
// specifiers apply to both the real and imaginary parts of the
|
||||
// complex number.
|
||||
import std.format : format;
|
||||
assert(format("%.2f", c) == "1.20+3.40i");
|
||||
assert(format("%4.1f", c) == " 1.2+ 3.4i");
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
static import core.math;
|
||||
assert(abs(complex(1.0)) == 1.0);
|
||||
assert(abs(complex(0.0, 1.0)) == 1.0);
|
||||
assert(abs(complex(1.0L, -2.0L)) == core.math.sqrt(5.0L));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
assert(sqAbs(complex(0.0)) == 0.0);
|
||||
assert(sqAbs(complex(1.0)) == 1.0);
|
||||
assert(sqAbs(complex(0.0, 1.0)) == 1.0);
|
||||
assert(isClose(sqAbs(complex(1.0L, -2.0L)), 5.0L));
|
||||
assert(isClose(sqAbs(complex(-3.0L, 1.0L)), 10.0L));
|
||||
assert(isClose(sqAbs(complex(1.0f,-1.0f)), 2.0f));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.constants : PI_2, PI_4;
|
||||
assert(arg(complex(1.0)) == 0.0);
|
||||
assert(arg(complex(0.0L, 1.0L)) == PI_2);
|
||||
assert(arg(complex(1.0L, 1.0L)) == PI_4);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.constants : PI;
|
||||
assert(norm(complex(3.0, 4.0)) == 25.0);
|
||||
assert(norm(fromPolar(5.0, 0.0)) == 25.0);
|
||||
assert(isClose(norm(fromPolar(5.0L, PI / 6)), 25.0L));
|
||||
assert(isClose(norm(fromPolar(5.0L, 13 * PI / 6)), 25.0L));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
assert(conj(complex(1.0)) == complex(1.0));
|
||||
assert(conj(complex(1.0, 2.0)) == complex(1.0, -2.0));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
assert(proj(complex(1.0)) == complex(1.0));
|
||||
assert(proj(complex(double.infinity, 5.0)) == complex(double.infinity, 0.0));
|
||||
assert(proj(complex(5.0, -double.infinity)) == complex(double.infinity, -0.0));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import core.math;
|
||||
import std.math.operations : isClose;
|
||||
import std.math.algebraic : sqrt;
|
||||
import std.math.constants : PI_4;
|
||||
auto z = fromPolar(core.math.sqrt(2.0L), PI_4);
|
||||
assert(isClose(z.re, 1.0L));
|
||||
assert(isClose(z.im, 1.0L));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
static import core.math;
|
||||
assert(sin(complex(0.0)) == 0.0);
|
||||
assert(sin(complex(2.0, 0)) == core.math.sin(2.0));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
static import core.math;
|
||||
static import std.math;
|
||||
assert(cos(complex(0.0)) == 1.0);
|
||||
assert(cos(complex(1.3, 0.0)) == core.math.cos(1.3));
|
||||
assert(cos(complex(0.0, 5.2)) == std.math.cosh(5.2));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
static import std.math;
|
||||
|
||||
int ceqrel(T)(const Complex!T x, const Complex!T y) @safe pure nothrow @nogc
|
||||
{
|
||||
import std.math.operations : feqrel;
|
||||
const r = feqrel(x.re, y.re);
|
||||
const i = feqrel(x.im, y.im);
|
||||
return r < i ? r : i;
|
||||
}
|
||||
assert(ceqrel(tan(complex(1.0, 0.0)), complex(std.math.tan(1.0), 0.0)) >= double.mant_dig - 2);
|
||||
assert(ceqrel(tan(complex(0.0, 1.0)), complex(0.0, std.math.tanh(1.0))) >= double.mant_dig - 2);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.constants : PI;
|
||||
assert(asin(complex(0.0)) == 0.0);
|
||||
assert(isClose(asin(complex(0.5L)), PI / 6));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.constants : PI;
|
||||
import std.math.trigonometry : std_math_acos = acos;
|
||||
assert(acos(complex(0.0)) == std_math_acos(0.0));
|
||||
assert(isClose(acos(complex(0.5L)), PI / 3));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.constants : PI;
|
||||
assert(atan(complex(0.0)) == 0.0);
|
||||
assert(isClose(atan(sqrt(complex(3.0L))), PI / 3));
|
||||
assert(isClose(atan(sqrt(complex(3.0f))), float(PI) / 3));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
static import std.math;
|
||||
assert(sinh(complex(0.0)) == 0.0);
|
||||
assert(sinh(complex(1.0L)) == std.math.sinh(1.0L));
|
||||
assert(sinh(complex(1.0f)) == std.math.sinh(1.0f));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
static import std.math;
|
||||
assert(cosh(complex(0.0)) == 1.0);
|
||||
assert(cosh(complex(1.0L)) == std.math.cosh(1.0L));
|
||||
assert(cosh(complex(1.0f)) == std.math.cosh(1.0f));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.trigonometry : std_math_tanh = tanh;
|
||||
assert(tanh(complex(0.0)) == 0.0);
|
||||
assert(isClose(tanh(complex(1.0L)), std_math_tanh(1.0L)));
|
||||
assert(isClose(tanh(complex(1.0f)), std_math_tanh(1.0f)));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.trigonometry : std_math_asinh = asinh;
|
||||
assert(asinh(complex(0.0)) == 0.0);
|
||||
assert(isClose(asinh(complex(1.0L)), std_math_asinh(1.0L)));
|
||||
assert(isClose(asinh(complex(1.0f)), std_math_asinh(1.0f)));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.trigonometry : std_math_acosh = acosh;
|
||||
assert(acosh(complex(1.0)) == 0.0);
|
||||
assert(isClose(acosh(complex(3.0L)), std_math_acosh(3.0L)));
|
||||
assert(isClose(acosh(complex(3.0f)), std_math_acosh(3.0f)));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.trigonometry : std_math_atanh = atanh;
|
||||
assert(atanh(complex(0.0)) == 0.0);
|
||||
assert(isClose(atanh(complex(0.5L)), std_math_atanh(0.5L)));
|
||||
assert(isClose(atanh(complex(0.5f)), std_math_atanh(0.5f)));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import core.math : cos, sin;
|
||||
assert(expi(0.0L) == 1.0L);
|
||||
assert(expi(1.3e5L) == complex(cos(1.3e5L), sin(1.3e5L)));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.trigonometry : cosh, sinh;
|
||||
assert(coshisinh(3.0L) == complex(cosh(3.0L), sinh(3.0L)));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
static import core.math;
|
||||
assert(sqrt(complex(0.0)) == 0.0);
|
||||
assert(sqrt(complex(1.0L, 0)) == core.math.sqrt(1.0L));
|
||||
assert(sqrt(complex(-1.0L, 0)) == complex(0, 1.0L));
|
||||
assert(sqrt(complex(-8.0, -6.0)) == complex(1.0, -3.0));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.constants : PI;
|
||||
|
||||
assert(exp(complex(0.0, 0.0)) == complex(1.0, 0.0));
|
||||
|
||||
auto a = complex(2.0, 1.0);
|
||||
assert(exp(conj(a)) == conj(exp(a)));
|
||||
|
||||
auto b = exp(complex(0.0L, 1.0L) * PI);
|
||||
assert(isClose(b, -1.0L, 0.0, 1e-15));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import core.math : sqrt;
|
||||
import std.math.constants : PI;
|
||||
import std.math.operations : isClose;
|
||||
|
||||
auto a = complex(2.0, 1.0);
|
||||
assert(log(conj(a)) == conj(log(a)));
|
||||
|
||||
auto b = 2.0 * log10(complex(0.0, 1.0));
|
||||
auto c = 4.0 * log10(complex(sqrt(2.0) / 2, sqrt(2.0) / 2));
|
||||
assert(isClose(b, c, 0.0, 1e-15));
|
||||
|
||||
assert(log(complex(-1.0L, 0.0L)) == complex(0.0L, PI));
|
||||
assert(log(complex(-1.0L, -0.0L)) == complex(0.0L, -PI));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import core.math : sqrt;
|
||||
import std.math.constants : LN10, PI;
|
||||
import std.math.operations : isClose;
|
||||
|
||||
auto a = complex(2.0, 1.0);
|
||||
assert(log10(a) == log(a) / log(complex(10.0)));
|
||||
|
||||
auto b = log10(complex(0.0, 1.0)) * 2.0;
|
||||
auto c = log10(complex(sqrt(2.0) / 2, sqrt(2.0) / 2)) * 4.0;
|
||||
assert(isClose(b, c, 0.0, 1e-15));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
auto a = complex(1.0, 2.0);
|
||||
assert(pow(a, 2) == a * a);
|
||||
assert(pow(a, 3) == a * a * a);
|
||||
assert(pow(a, -2) == 1.0 / (a * a));
|
||||
assert(isClose(pow(a, -3), 1.0 / (a * a * a)));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
assert(pow(complex(0.0), 2.0) == complex(0.0));
|
||||
assert(pow(complex(5.0), 2.0) == complex(25.0));
|
||||
|
||||
auto a = pow(complex(-1.0, 0.0), 0.5);
|
||||
assert(isClose(a, complex(0.0, +1.0), 0.0, 1e-16));
|
||||
|
||||
auto b = pow(complex(-1.0, -0.0), 0.5);
|
||||
assert(isClose(b, complex(0.0, -1.0), 0.0, 1e-16));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.exponential : exp;
|
||||
import std.math.constants : PI;
|
||||
auto a = complex(0.0);
|
||||
auto b = complex(2.0);
|
||||
assert(pow(a, b) == complex(0.0));
|
||||
|
||||
auto c = complex(0.0L, 1.0L);
|
||||
assert(isClose(pow(c, c), exp((-PI) / 2)));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.complex;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
assert(pow(2.0, complex(0.0)) == complex(1.0));
|
||||
assert(pow(2.0, complex(5.0)) == complex(32.0));
|
||||
|
||||
auto a = pow(-2.0, complex(-1.0));
|
||||
assert(isClose(a, complex(-0.5), 0.0, 1e-16));
|
||||
|
||||
auto b = pow(-0.5, complex(-1.0));
|
||||
assert(isClose(b, complex(-2.0), 0.0, 1e-15));
|
||||
}
|
||||
|
235
libphobos/testsuite/libphobos.phobos/std_concurrency.d
Normal file
235
libphobos/testsuite/libphobos.phobos/std_concurrency.d
Normal file
|
@ -0,0 +1,235 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
__gshared string received;
|
||||
static void spawnedFunc(Tid ownerTid)
|
||||
{
|
||||
import std.conv : text;
|
||||
// Receive a message from the owner thread.
|
||||
receive((int i){
|
||||
received = text("Received the number ", i);
|
||||
|
||||
// Send a message back to the owner thread
|
||||
// indicating success.
|
||||
send(ownerTid, true);
|
||||
});
|
||||
}
|
||||
|
||||
// Start spawnedFunc in a new thread.
|
||||
auto childTid = spawn(&spawnedFunc, thisTid);
|
||||
|
||||
// Send the number 42 to this new thread.
|
||||
send(childTid, 42);
|
||||
|
||||
// Receive the result code.
|
||||
auto wasSuccessful = receiveOnly!(bool);
|
||||
assert(wasSuccessful);
|
||||
assert(received == "Received the number 42");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
static void f(string msg)
|
||||
{
|
||||
assert(msg == "Hello World");
|
||||
}
|
||||
|
||||
auto tid = spawn(&f, "Hello World");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
string msg = "Hello, World!";
|
||||
|
||||
static void f1(string msg) {}
|
||||
static assert(!__traits(compiles, spawn(&f1, msg.dup)));
|
||||
static assert( __traits(compiles, spawn(&f1, msg.idup)));
|
||||
|
||||
static void f2(char[] msg) {}
|
||||
static assert(!__traits(compiles, spawn(&f2, msg.dup)));
|
||||
static assert(!__traits(compiles, spawn(&f2, msg.idup)));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
spawn({
|
||||
ownerTid.send("This is so great!");
|
||||
});
|
||||
assert(receiveOnly!string == "This is so great!");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
import std.variant : Variant;
|
||||
|
||||
auto process = ()
|
||||
{
|
||||
receive(
|
||||
(int i) { ownerTid.send(1); },
|
||||
(double f) { ownerTid.send(2); },
|
||||
(Variant v) { ownerTid.send(3); }
|
||||
);
|
||||
};
|
||||
|
||||
{
|
||||
auto tid = spawn(process);
|
||||
send(tid, 42);
|
||||
assert(receiveOnly!int == 1);
|
||||
}
|
||||
|
||||
{
|
||||
auto tid = spawn(process);
|
||||
send(tid, 3.14);
|
||||
assert(receiveOnly!int == 2);
|
||||
}
|
||||
|
||||
{
|
||||
auto tid = spawn(process);
|
||||
send(tid, "something else");
|
||||
assert(receiveOnly!int == 3);
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
auto tid = spawn(
|
||||
{
|
||||
assert(receiveOnly!int == 42);
|
||||
});
|
||||
send(tid, 42);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
auto tid = spawn(
|
||||
{
|
||||
assert(receiveOnly!string == "text");
|
||||
});
|
||||
send(tid, "text");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
struct Record { string name; int age; }
|
||||
|
||||
auto tid = spawn(
|
||||
{
|
||||
auto msg = receiveOnly!(double, Record);
|
||||
assert(msg[0] == 0.5);
|
||||
assert(msg[1].name == "Alice");
|
||||
assert(msg[1].age == 31);
|
||||
});
|
||||
|
||||
send(tid, 0.5, Record("Alice", 31));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
auto tid = spawn({
|
||||
int i;
|
||||
while (i < 9)
|
||||
i = receiveOnly!int;
|
||||
|
||||
ownerTid.send(i * 2);
|
||||
});
|
||||
|
||||
auto r = new Generator!int({
|
||||
foreach (i; 1 .. 10)
|
||||
yield(i);
|
||||
});
|
||||
|
||||
foreach (e; r)
|
||||
tid.send(e);
|
||||
|
||||
assert(receiveOnly!int == 18);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
import std.range;
|
||||
|
||||
InputRange!int myIota = iota(10).inputRangeObject;
|
||||
|
||||
myIota.popFront();
|
||||
myIota.popFront();
|
||||
assert(myIota.moveFront == 2);
|
||||
assert(myIota.front == 2);
|
||||
myIota.popFront();
|
||||
assert(myIota.front == 3);
|
||||
|
||||
//can be assigned to std.range.interfaces.InputRange directly
|
||||
myIota = new Generator!int(
|
||||
{
|
||||
foreach (i; 0 .. 10) yield(i);
|
||||
});
|
||||
|
||||
myIota.popFront();
|
||||
myIota.popFront();
|
||||
assert(myIota.moveFront == 2);
|
||||
assert(myIota.front == 2);
|
||||
myIota.popFront();
|
||||
assert(myIota.front == 3);
|
||||
|
||||
size_t[2] counter = [0, 0];
|
||||
foreach (i, unused; myIota) counter[] += [1, i];
|
||||
|
||||
assert(myIota.empty);
|
||||
assert(counter == [7, 21]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
static class MySingleton
|
||||
{
|
||||
static MySingleton instance()
|
||||
{
|
||||
__gshared MySingleton inst;
|
||||
return initOnce!inst(new MySingleton);
|
||||
}
|
||||
}
|
||||
|
||||
assert(MySingleton.instance !is null);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.concurrency;
|
||||
|
||||
import core.sync.mutex : Mutex;
|
||||
|
||||
static shared bool varA, varB;
|
||||
static shared Mutex m;
|
||||
m = new shared Mutex;
|
||||
|
||||
spawn({
|
||||
// use a different mutex for varB to avoid a dead-lock
|
||||
initOnce!varB(true, m);
|
||||
ownerTid.send(true);
|
||||
});
|
||||
// init depends on the result of the spawned thread
|
||||
initOnce!varA(receiveOnly!bool);
|
||||
assert(varA == true);
|
||||
assert(varB == true);
|
||||
}
|
||||
|
56
libphobos/testsuite/libphobos.phobos/std_container_array.d
Normal file
56
libphobos/testsuite/libphobos.phobos/std_container_array.d
Normal file
|
@ -0,0 +1,56 @@
|
|||
pure @system unittest
|
||||
{
|
||||
import std.container.array;
|
||||
|
||||
auto arr = Array!int(0, 2, 3);
|
||||
assert(arr[0] == 0);
|
||||
assert(arr.front == 0);
|
||||
assert(arr.back == 3);
|
||||
|
||||
// reserve space
|
||||
arr.reserve(1000);
|
||||
assert(arr.length == 3);
|
||||
assert(arr.capacity >= 1000);
|
||||
|
||||
// insertion
|
||||
arr.insertBefore(arr[1..$], 1);
|
||||
assert(arr.front == 0);
|
||||
assert(arr.length == 4);
|
||||
|
||||
arr.insertBack(4);
|
||||
assert(arr.back == 4);
|
||||
assert(arr.length == 5);
|
||||
|
||||
// set elements
|
||||
arr[1] *= 42;
|
||||
assert(arr[1] == 42);
|
||||
}
|
||||
|
||||
pure @system unittest
|
||||
{
|
||||
import std.container.array;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
auto arr = Array!int(1, 2, 3);
|
||||
|
||||
// concat
|
||||
auto b = Array!int(11, 12, 13);
|
||||
arr ~= b;
|
||||
assert(arr.length == 6);
|
||||
|
||||
// slicing
|
||||
assert(arr[1 .. 3].equal([2, 3]));
|
||||
|
||||
// remove
|
||||
arr.linearRemove(arr[1 .. 3]);
|
||||
assert(arr[0 .. 2].equal([1, 11]));
|
||||
}
|
||||
|
||||
pure @system unittest
|
||||
{
|
||||
import std.container.array;
|
||||
|
||||
auto arr = Array!bool([true, true, false, true, false]);
|
||||
assert(arr.length == 5);
|
||||
}
|
||||
|
102
libphobos/testsuite/libphobos.phobos/std_container_binaryheap.d
Normal file
102
libphobos/testsuite/libphobos.phobos/std_container_binaryheap.d
Normal file
|
@ -0,0 +1,102 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.container.binaryheap;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : take;
|
||||
auto maxHeap = heapify([4, 7, 3, 1, 5]);
|
||||
assert(maxHeap.take(3).equal([7, 5, 4]));
|
||||
|
||||
auto minHeap = heapify!"a > b"([4, 7, 3, 1, 5]);
|
||||
assert(minHeap.take(3).equal([1, 3, 4]));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.container.binaryheap;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
|
||||
auto h = heapify(a);
|
||||
// largest element
|
||||
assert(h.front == 16);
|
||||
// a has the heap property
|
||||
assert(equal(a, [ 16, 14, 10, 8, 7, 9, 3, 2, 4, 1 ]));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.container.binaryheap;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : take;
|
||||
int[] a = [4, 1, 3, 2, 16, 9, 10, 14, 8, 7];
|
||||
auto top5 = heapify(a).take(5);
|
||||
assert(top5.equal([16, 14, 10, 9, 8]));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.container.binaryheap;
|
||||
|
||||
import std.conv : to;
|
||||
import std.range.primitives;
|
||||
{
|
||||
// example from "Introduction to Algorithms" Cormen et al., p 146
|
||||
int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
|
||||
auto h = heapify(a);
|
||||
h = heapify!"a < b"(a);
|
||||
assert(h.front == 16);
|
||||
assert(a == [ 16, 14, 10, 8, 7, 9, 3, 2, 4, 1 ]);
|
||||
auto witness = [ 16, 14, 10, 9, 8, 7, 4, 3, 2, 1 ];
|
||||
for (; !h.empty; h.removeFront(), witness.popFront())
|
||||
{
|
||||
assert(!witness.empty);
|
||||
assert(witness.front == h.front);
|
||||
}
|
||||
assert(witness.empty);
|
||||
}
|
||||
{
|
||||
int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
|
||||
int[] b = new int[a.length];
|
||||
BinaryHeap!(int[]) h = BinaryHeap!(int[])(b, 0);
|
||||
foreach (e; a)
|
||||
{
|
||||
h.insert(e);
|
||||
}
|
||||
assert(b == [ 16, 14, 10, 8, 7, 3, 9, 1, 4, 2 ], to!string(b));
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.container.binaryheap;
|
||||
|
||||
import std.stdio;
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.container.binaryheap;
|
||||
|
||||
int[] a = [ 4, 1, 3, 2, 16, 9, 10, 14, 8, 7 ];
|
||||
auto h = heapify(a);
|
||||
|
||||
// Internal representation of Binary Heap tree
|
||||
assert(a.equal([16, 14, 10, 8, 7, 9, 3, 2, 4, 1]));
|
||||
|
||||
h.replaceFront(30);
|
||||
// Value 16 was replaced by 30
|
||||
assert(a.equal([30, 14, 10, 8, 7, 9, 3, 2, 4, 1]));
|
||||
|
||||
// Making changes to the Store will be seen in the Heap
|
||||
a[0] = 40;
|
||||
assert(h.front() == 40);
|
||||
|
||||
// Inserting a new element will reallocate the Store, leaving
|
||||
// the original Store unchanged.
|
||||
h.insert(20);
|
||||
assert(a.equal([40, 14, 10, 8, 7, 9, 3, 2, 4, 1]));
|
||||
|
||||
// Making changes to the original Store will not affect the Heap anymore
|
||||
a[0] = 60;
|
||||
assert(h.front() == 40);
|
||||
}
|
||||
|
47
libphobos/testsuite/libphobos.phobos/std_container_dlist.d
Normal file
47
libphobos/testsuite/libphobos.phobos/std_container_dlist.d
Normal file
|
@ -0,0 +1,47 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.container.dlist;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.container : DList;
|
||||
|
||||
auto s = DList!int(1, 2, 3);
|
||||
assert(equal(s[], [1, 2, 3]));
|
||||
|
||||
s.removeFront();
|
||||
assert(equal(s[], [2, 3]));
|
||||
s.removeBack();
|
||||
assert(equal(s[], [2]));
|
||||
|
||||
s.insertFront([4, 5]);
|
||||
assert(equal(s[], [4, 5, 2]));
|
||||
s.insertBack([6, 7]);
|
||||
assert(equal(s[], [4, 5, 2, 6, 7]));
|
||||
|
||||
// If you want to apply range operations, simply slice it.
|
||||
import std.algorithm.searching : countUntil;
|
||||
import std.range : popFrontN, popBackN, walkLength;
|
||||
|
||||
auto sl = DList!int([1, 2, 3, 4, 5]);
|
||||
assert(countUntil(sl[], 2) == 1);
|
||||
|
||||
auto r = sl[];
|
||||
popFrontN(r, 2);
|
||||
popBackN(r, 2);
|
||||
assert(r.equal([3]));
|
||||
assert(walkLength(r) == 1);
|
||||
|
||||
// DList.Range can be used to remove elements from the list it spans
|
||||
auto nl = DList!int([1, 2, 3, 4, 5]);
|
||||
for (auto rn = nl[]; !rn.empty;)
|
||||
if (rn.front % 2 == 0)
|
||||
nl.popFirstOf(rn);
|
||||
else
|
||||
rn.popFront();
|
||||
assert(equal(nl[], [1, 3, 5]));
|
||||
auto rs = nl[];
|
||||
rs.popFront();
|
||||
nl.remove(rs);
|
||||
assert(equal(nl[], [1]));
|
||||
}
|
||||
|
60
libphobos/testsuite/libphobos.phobos/std_container_rbtree.d
Normal file
60
libphobos/testsuite/libphobos.phobos/std_container_rbtree.d
Normal file
|
@ -0,0 +1,60 @@
|
|||
@safe pure unittest
|
||||
{
|
||||
import std.container.rbtree;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.container.rbtree;
|
||||
|
||||
auto rbt = redBlackTree(3, 1, 4, 2, 5);
|
||||
assert(rbt.front == 1);
|
||||
assert(equal(rbt[], [1, 2, 3, 4, 5]));
|
||||
|
||||
rbt.removeKey(1, 4);
|
||||
assert(equal(rbt[], [2, 3, 5]));
|
||||
|
||||
rbt.removeFront();
|
||||
assert(equal(rbt[], [3, 5]));
|
||||
|
||||
rbt.insert([1, 2, 4]);
|
||||
assert(equal(rbt[], [1, 2, 3, 4, 5]));
|
||||
|
||||
// Query bounds in O(log(n))
|
||||
assert(rbt.lowerBound(3).equal([1, 2]));
|
||||
assert(rbt.equalRange(3).equal([3]));
|
||||
assert(rbt.upperBound(3).equal([4, 5]));
|
||||
|
||||
// A Red Black tree with the highest element at front:
|
||||
import std.range : iota;
|
||||
auto maxTree = redBlackTree!"a > b"(iota(5));
|
||||
assert(equal(maxTree[], [4, 3, 2, 1, 0]));
|
||||
|
||||
// adding duplicates will not add them, but return 0
|
||||
auto rbt2 = redBlackTree(1, 3);
|
||||
assert(rbt2.insert(1) == 0);
|
||||
assert(equal(rbt2[], [1, 3]));
|
||||
assert(rbt2.insert(2) == 1);
|
||||
|
||||
// however you can allow duplicates
|
||||
auto ubt = redBlackTree!true([0, 1, 0, 1]);
|
||||
assert(equal(ubt[], [0, 0, 1, 1]));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.container.rbtree;
|
||||
|
||||
import std.range : iota;
|
||||
|
||||
auto rbt1 = redBlackTree(0, 1, 5, 7);
|
||||
auto rbt2 = redBlackTree!string("hello", "world");
|
||||
auto rbt3 = redBlackTree!true(0, 1, 5, 7, 5);
|
||||
auto rbt4 = redBlackTree!"a > b"(0, 1, 5, 7);
|
||||
auto rbt5 = redBlackTree!("a > b", true)(0.1, 1.3, 5.9, 7.2, 5.9);
|
||||
|
||||
// also works with ranges
|
||||
auto rbt6 = redBlackTree(iota(3));
|
||||
auto rbt7 = redBlackTree!true(iota(3));
|
||||
auto rbt8 = redBlackTree!"a > b"(iota(3));
|
||||
auto rbt9 = redBlackTree!("a > b", true)(iota(3));
|
||||
}
|
||||
|
28
libphobos/testsuite/libphobos.phobos/std_container_slist.d
Normal file
28
libphobos/testsuite/libphobos.phobos/std_container_slist.d
Normal file
|
@ -0,0 +1,28 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.container.slist;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.container : SList;
|
||||
|
||||
auto s = SList!int(1, 2, 3);
|
||||
assert(equal(s[], [1, 2, 3]));
|
||||
|
||||
s.removeFront();
|
||||
assert(equal(s[], [2, 3]));
|
||||
|
||||
s.insertFront([5, 6]);
|
||||
assert(equal(s[], [5, 6, 2, 3]));
|
||||
|
||||
// If you want to apply range operations, simply slice it.
|
||||
import std.algorithm.searching : countUntil;
|
||||
import std.range : popFrontN, walkLength;
|
||||
|
||||
auto sl = SList!int(1, 2, 3, 4, 5);
|
||||
assert(countUntil(sl[], 2) == 1);
|
||||
|
||||
auto r = sl[];
|
||||
popFrontN(r, 2);
|
||||
assert(walkLength(r) == 3);
|
||||
}
|
||||
|
51
libphobos/testsuite/libphobos.phobos/std_container_util.d
Normal file
51
libphobos/testsuite/libphobos.phobos/std_container_util.d
Normal file
|
@ -0,0 +1,51 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.container.util;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.container;
|
||||
|
||||
auto arr = make!(Array!int)([4, 2, 3, 1]);
|
||||
assert(equal(arr[], [4, 2, 3, 1]));
|
||||
|
||||
auto rbt = make!(RedBlackTree!(int, "a > b"))([4, 2, 3, 1]);
|
||||
assert(equal(rbt[], [4, 3, 2, 1]));
|
||||
|
||||
alias makeList = make!(SList!int);
|
||||
auto slist = makeList(1, 2, 3);
|
||||
assert(equal(slist[], [1, 2, 3]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.container.util;
|
||||
|
||||
import std.container.array : Array;
|
||||
import std.range : only, repeat;
|
||||
import std.range.primitives : isInfinite;
|
||||
static assert(__traits(compiles, { auto arr = make!Array(only(5)); }));
|
||||
static assert(!__traits(compiles, { auto arr = make!Array(repeat(5)); }));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.container.util;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.container.array, std.container.rbtree, std.container.slist;
|
||||
import std.range : iota;
|
||||
|
||||
auto arr = make!Array(iota(5));
|
||||
assert(equal(arr[], [0, 1, 2, 3, 4]));
|
||||
|
||||
auto rbtmax = make!(RedBlackTree, "a > b")(iota(5));
|
||||
assert(equal(rbtmax[], [4, 3, 2, 1, 0]));
|
||||
|
||||
auto rbtmin = make!RedBlackTree(4, 1, 3, 2);
|
||||
assert(equal(rbtmin[], [1, 2, 3, 4]));
|
||||
|
||||
alias makeList = make!SList;
|
||||
auto list = makeList(1, 7, 42);
|
||||
assert(equal(list[], [1, 7, 42]));
|
||||
}
|
||||
|
511
libphobos/testsuite/libphobos.phobos/std_conv.d
Normal file
511
libphobos/testsuite/libphobos.phobos/std_conv.d
Normal file
|
@ -0,0 +1,511 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
assertThrown!ConvException(to!int("abc"));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
assertThrown!ConvOverflowException(to!ubyte(1_000_000));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
int a = 42;
|
||||
int b = to!int(a);
|
||||
double c = to!double(3.14); // c is double with value 3.14
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
int a = 420;
|
||||
assert(to!long(a) == a);
|
||||
assertThrown!ConvOverflowException(to!byte(a));
|
||||
|
||||
assert(to!int(4.2e6) == 4200000);
|
||||
assertThrown!ConvOverflowException(to!uint(-3.14));
|
||||
assert(to!uint(3.14) == 3);
|
||||
assert(to!uint(3.99) == 3);
|
||||
assert(to!int(-3.99) == -3);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
auto str = to!string(42, 16);
|
||||
assert(str == "2A");
|
||||
auto i = to!int(str, 16);
|
||||
assert(i == 42);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
// 2^24 - 1, largest proper integer representable as float
|
||||
int a = 16_777_215;
|
||||
assert(to!int(to!float(a)) == a);
|
||||
assert(to!int(to!float(-a)) == -a);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
assert(to!char("a") == 'a');
|
||||
assertThrown(to!char("ñ")); // 'ñ' does not fit into a char
|
||||
assert(to!wchar("ñ") == 'ñ');
|
||||
assertThrown(to!wchar("😃")); // '😃' does not fit into a wchar
|
||||
assert(to!dchar("😃") == '😃');
|
||||
|
||||
// Using wstring or dstring as source type does not affect the result
|
||||
assert(to!char("a"w) == 'a');
|
||||
assert(to!char("a"d) == 'a');
|
||||
|
||||
// Two code points cannot be converted to a single one
|
||||
assertThrown(to!char("ab"));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.string : split;
|
||||
|
||||
int[] a = [1, 2, 3];
|
||||
auto b = to!(float[])(a);
|
||||
assert(b == [1.0f, 2, 3]);
|
||||
string str = "1 2 3 4 5 6";
|
||||
auto numbers = to!(double[])(split(str));
|
||||
assert(numbers == [1.0, 2, 3, 4, 5, 6]);
|
||||
int[string] c;
|
||||
c["a"] = 1;
|
||||
c["b"] = 2;
|
||||
auto d = to!(double[wstring])(c);
|
||||
assert(d["a"w] == 1 && d["b"w] == 2);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
int[string][double[int[]]] a;
|
||||
auto b = to!(short[wstring][string[double[]]])(a);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
// Testing object conversions
|
||||
class A {}
|
||||
class B : A {}
|
||||
class C : A {}
|
||||
A a1 = new A, a2 = new B, a3 = new C;
|
||||
assert(to!B(a2) is a2);
|
||||
assert(to!C(a3) is a3);
|
||||
assertThrown!ConvException(to!B(a3));
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
// Conversion representing dynamic/static array with string
|
||||
long[] a = [ 1, 3, 5 ];
|
||||
assert(to!string(a) == "[1, 3, 5]");
|
||||
|
||||
// Conversion representing associative array with string
|
||||
int[string] associativeArray = ["0":1, "1":2];
|
||||
assert(to!string(associativeArray) == `["0":1, "1":2]` ||
|
||||
to!string(associativeArray) == `["1":2, "0":1]`);
|
||||
|
||||
// char* to string conversion
|
||||
assert(to!string(cast(char*) null) == "");
|
||||
assert(to!string("foo\0".ptr) == "foo");
|
||||
|
||||
// Conversion reinterpreting void array to string
|
||||
auto w = "abcx"w;
|
||||
const(void)[] b = w;
|
||||
assert(b.length == 8);
|
||||
|
||||
auto c = to!(wchar[])(b);
|
||||
assert(c == "abcx");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
enum E { a, b, c }
|
||||
assert(to!E("a") == E.a);
|
||||
assert(to!E("b") == E.b);
|
||||
assertThrown!ConvException(to!E("A"));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
assert(roundTo!int(3.14) == 3);
|
||||
assert(roundTo!int(3.49) == 3);
|
||||
assert(roundTo!int(3.5) == 4);
|
||||
assert(roundTo!int(3.999) == 4);
|
||||
assert(roundTo!int(-3.14) == -3);
|
||||
assert(roundTo!int(-3.49) == -3);
|
||||
assert(roundTo!int(-3.5) == -4);
|
||||
assert(roundTo!int(-3.999) == -4);
|
||||
assert(roundTo!(const int)(to!(const double)(-3.999)) == -4);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.typecons : Flag, Yes, No;
|
||||
auto s = "true";
|
||||
bool b = parse!bool(s);
|
||||
assert(b);
|
||||
auto s2 = "true";
|
||||
bool b2 = parse!(bool, string, No.doCount)(s2);
|
||||
assert(b2);
|
||||
auto s3 = "true";
|
||||
auto b3 = parse!(bool, string, Yes.doCount)(s3);
|
||||
assert(b3.data && b3.count == 4);
|
||||
auto s4 = "falSE";
|
||||
auto b4 = parse!(bool, string, Yes.doCount)(s4);
|
||||
assert(!b4.data && b4.count == 5);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.typecons : Flag, Yes, No;
|
||||
string s = "123";
|
||||
auto a = parse!int(s);
|
||||
assert(a == 123);
|
||||
|
||||
string s1 = "123";
|
||||
auto a1 = parse!(int, string, Yes.doCount)(s1);
|
||||
assert(a1.data == 123 && a1.count == 3);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.string : tr;
|
||||
import std.typecons : Flag, Yes, No;
|
||||
string test = "123 \t 76.14";
|
||||
auto a = parse!uint(test);
|
||||
assert(a == 123);
|
||||
assert(test == " \t 76.14"); // parse bumps string
|
||||
test = tr(test, " \t\n\r", "", "d"); // skip ws
|
||||
assert(test == "76.14");
|
||||
auto b = parse!double(test);
|
||||
assert(b == 76.14);
|
||||
assert(test == "");
|
||||
|
||||
string test2 = "123 \t 76.14";
|
||||
auto a2 = parse!(uint, string, Yes.doCount)(test2);
|
||||
assert(a2.data == 123 && a2.count == 3);
|
||||
assert(test2 == " \t 76.14");// parse bumps string
|
||||
test2 = tr(test2, " \t\n\r", "", "d"); // skip ws
|
||||
assert(test2 == "76.14");
|
||||
auto b2 = parse!(double, string, Yes.doCount)(test2);
|
||||
assert(b2.data == 76.14 && b2.count == 5);
|
||||
assert(test2 == "");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.typecons : Flag, Yes, No, tuple;
|
||||
enum EnumType : bool { a = true, b = false, c = a }
|
||||
|
||||
auto str = "a";
|
||||
assert(parse!EnumType(str) == EnumType.a);
|
||||
auto str2 = "a";
|
||||
assert(parse!(EnumType, string, No.doCount)(str2) == EnumType.a);
|
||||
auto str3 = "a";
|
||||
assert(parse!(EnumType, string, Yes.doCount)(str3) == tuple(EnumType.a, 1));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.traits : isNaN, isInfinity;
|
||||
import std.typecons : Flag, Yes, No;
|
||||
auto str = "123.456";
|
||||
assert(parse!double(str).isClose(123.456));
|
||||
auto str2 = "123.456";
|
||||
assert(parse!(double, string, No.doCount)(str2).isClose(123.456));
|
||||
auto str3 = "123.456";
|
||||
auto r = parse!(double, string, Yes.doCount)(str3);
|
||||
assert(r.data.isClose(123.456));
|
||||
assert(r.count == 7);
|
||||
auto str4 = "-123.456";
|
||||
r = parse!(double, string, Yes.doCount)(str4);
|
||||
assert(r.data.isClose(-123.456));
|
||||
assert(r.count == 8);
|
||||
auto str5 = "+123.456";
|
||||
r = parse!(double, string, Yes.doCount)(str5);
|
||||
assert(r.data.isClose(123.456));
|
||||
assert(r.count == 8);
|
||||
auto str6 = "inf0";
|
||||
r = parse!(double, string, Yes.doCount)(str6);
|
||||
assert(isInfinity(r.data) && r.count == 3 && str6 == "0");
|
||||
auto str7 = "-0";
|
||||
auto r2 = parse!(float, string, Yes.doCount)(str7);
|
||||
assert(r2.data.isClose(0.0) && r2.count == 2);
|
||||
auto str8 = "nan";
|
||||
auto r3 = parse!(real, string, Yes.doCount)(str8);
|
||||
assert(isNaN(r3.data) && r3.count == 3);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.typecons : Flag, Yes, No;
|
||||
auto s = "Hello, World!";
|
||||
char first = parse!char(s);
|
||||
assert(first == 'H');
|
||||
assert(s == "ello, World!");
|
||||
char second = parse!(char, string, No.doCount)(s);
|
||||
assert(second == 'e');
|
||||
assert(s == "llo, World!");
|
||||
auto third = parse!(char, string, Yes.doCount)(s);
|
||||
assert(third.data == 'l' && third.count == 1);
|
||||
assert(s == "lo, World!");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
import std.typecons : Flag, Yes, No;
|
||||
|
||||
alias NullType = typeof(null);
|
||||
auto s1 = "null";
|
||||
assert(parse!NullType(s1) is null);
|
||||
assert(s1 == "");
|
||||
|
||||
auto s2 = "NUll"d;
|
||||
assert(parse!NullType(s2) is null);
|
||||
assert(s2 == "");
|
||||
|
||||
auto s3 = "nuLlNULl";
|
||||
assert(parse!(NullType, string, No.doCount)(s3) is null);
|
||||
auto r = parse!(NullType, string, Yes.doCount)(s3);
|
||||
assert(r.data is null && r.count == 4);
|
||||
|
||||
auto m = "maybe";
|
||||
assertThrown!ConvException(parse!NullType(m));
|
||||
assertThrown!ConvException(parse!(NullType, string, Yes.doCount)(m));
|
||||
assert(m == "maybe"); // m shouldn't change on failure
|
||||
|
||||
auto s = "NULL";
|
||||
assert(parse!(const NullType)(s) is null);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.typecons : Flag, Yes, No;
|
||||
auto s1 = `[['h', 'e', 'l', 'l', 'o'], "world"]`;
|
||||
auto a1 = parse!(string[])(s1);
|
||||
assert(a1 == ["hello", "world"]);
|
||||
|
||||
auto s2 = `["aaa", "bbb", "ccc"]`;
|
||||
auto a2 = parse!(string[])(s2);
|
||||
assert(a2 == ["aaa", "bbb", "ccc"]);
|
||||
|
||||
auto s3 = `[['h', 'e', 'l', 'l', 'o'], "world"]`;
|
||||
auto len3 = s3.length;
|
||||
auto a3 = parse!(string[], string, Yes.doCount)(s3);
|
||||
assert(a3.data == ["hello", "world"]);
|
||||
assert(a3.count == len3);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.typecons : Flag, Yes, No, tuple;
|
||||
import std.range.primitives : save;
|
||||
import std.array : assocArray;
|
||||
auto s1 = "[1:10, 2:20, 3:30]";
|
||||
auto copyS1 = s1.save;
|
||||
auto aa1 = parse!(int[int])(s1);
|
||||
assert(aa1 == [1:10, 2:20, 3:30]);
|
||||
assert(tuple([1:10, 2:20, 3:30], copyS1.length) == parse!(int[int], string, Yes.doCount)(copyS1));
|
||||
|
||||
auto s2 = `["aaa":10, "bbb":20, "ccc":30]`;
|
||||
auto copyS2 = s2.save;
|
||||
auto aa2 = parse!(int[string])(s2);
|
||||
assert(aa2 == ["aaa":10, "bbb":20, "ccc":30]);
|
||||
assert(tuple(["aaa":10, "bbb":20, "ccc":30], copyS2.length) ==
|
||||
parse!(int[string], string, Yes.doCount)(copyS2));
|
||||
|
||||
auto s3 = `["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]`;
|
||||
auto copyS3 = s3.save;
|
||||
auto aa3 = parse!(int[][string])(s3);
|
||||
assert(aa3 == ["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]]);
|
||||
assert(tuple(["aaa":[1], "bbb":[2,3], "ccc":[4,5,6]], copyS3.length) ==
|
||||
parse!(int[][string], string, Yes.doCount)(copyS3));
|
||||
|
||||
auto s4 = `[]`;
|
||||
int[int] emptyAA;
|
||||
assert(tuple(emptyAA, s4.length) == parse!(int[int], string, Yes.doCount)(s4));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
assert( text(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"c);
|
||||
assert(wtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"w);
|
||||
assert(dtext(42, ' ', 1.5, ": xyz") == "42 1.5: xyz"d);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
// Same as 0177
|
||||
auto a = octal!177;
|
||||
// octal is a compile-time device
|
||||
enum b = octal!160;
|
||||
// Create an unsigned octal
|
||||
auto c = octal!"1_000_000u";
|
||||
// Leading zeros are allowed when converting from a string
|
||||
auto d = octal!"0001_200_000";
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.traits : Unsigned;
|
||||
immutable int s = 42;
|
||||
auto u1 = unsigned(s); //not qualified
|
||||
static assert(is(typeof(u1) == uint));
|
||||
Unsigned!(typeof(s)) u2 = unsigned(s); //same qualification
|
||||
static assert(is(typeof(u2) == immutable uint));
|
||||
immutable u3 = unsigned(s); //explicitly qualified
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.traits : Signed;
|
||||
|
||||
immutable uint u = 42;
|
||||
auto s1 = signed(u); //not qualified
|
||||
static assert(is(typeof(s1) == int));
|
||||
Signed!(typeof(u)) s2 = signed(u); //same qualification
|
||||
static assert(is(typeof(s2) == immutable int));
|
||||
immutable s3 = signed(u); //explicitly qualified
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
enum A { a = 42 }
|
||||
static assert(is(typeof(A.a.asOriginalType) == int));
|
||||
assert(A.a.asOriginalType == 42);
|
||||
enum B : double { a = 43 }
|
||||
static assert(is(typeof(B.a.asOriginalType) == double));
|
||||
assert(B.a.asOriginalType == 43);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
// Regular cast, which has been verified to be legal by the programmer:
|
||||
{
|
||||
long x;
|
||||
auto y = cast(int) x;
|
||||
}
|
||||
|
||||
// However this will still compile if 'x' is changed to be a pointer:
|
||||
{
|
||||
long* x;
|
||||
auto y = cast(int) x;
|
||||
}
|
||||
|
||||
// castFrom provides a more reliable alternative to casting:
|
||||
{
|
||||
long x;
|
||||
auto y = castFrom!long.to!int(x);
|
||||
}
|
||||
|
||||
// Changing the type of 'x' will now issue a compiler error,
|
||||
// allowing bad casts to be caught before it's too late:
|
||||
{
|
||||
long* x;
|
||||
static assert(
|
||||
!__traits(compiles, castFrom!long.to!int(x))
|
||||
);
|
||||
|
||||
// if cast is still needed, must be changed to:
|
||||
auto y = castFrom!(long*).to!int(x);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
// conversion at compile time
|
||||
auto string1 = hexString!"304A314B";
|
||||
assert(string1 == "0J1K");
|
||||
auto string2 = hexString!"304A314B"w;
|
||||
assert(string2 == "0J1K"w);
|
||||
auto string3 = hexString!"304A314B"d;
|
||||
assert(string3 == "0J1K"d);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.conv;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
assert(toChars(1).equal("1"));
|
||||
assert(toChars(1_000_000).equal("1000000"));
|
||||
|
||||
assert(toChars!(2)(2U).equal("10"));
|
||||
assert(toChars!(16)(255U).equal("ff"));
|
||||
assert(toChars!(16, char, LetterCase.upper)(255U).equal("FF"));
|
||||
}
|
||||
|
228
libphobos/testsuite/libphobos.phobos/std_csv.d
Normal file
228
libphobos/testsuite/libphobos.phobos/std_csv.d
Normal file
|
@ -0,0 +1,228 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.exception : collectException;
|
||||
import std.algorithm.searching : count;
|
||||
string text = "a,b,c\nHello,65";
|
||||
auto ex = collectException!CSVException(csvReader(text).count);
|
||||
assert(ex.toString == "(Row: 0, Col: 0) Row 2's length 2 does not match previous length of 3.");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.exception : collectException;
|
||||
import std.algorithm.searching : count;
|
||||
import std.typecons : Tuple;
|
||||
string text = "a,b\nHello,65";
|
||||
auto ex = collectException!CSVException(csvReader!(Tuple!(string,int))(text).count);
|
||||
assert(ex.toString == "(Row: 1, Col: 2) Unexpected 'b' when converting from type string to type int");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
string text = "a,\"b,c\nHello,65,2.5";
|
||||
assertThrown!IncompleteCellException(text.csvReader(["a","b","c"]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
string text = "a,b,c\nHello,65,2.5";
|
||||
assertThrown!HeaderMismatchException(text.csvReader(["b","c","invalid"]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.searching : count;
|
||||
import std.exception : assertThrown;
|
||||
|
||||
string text = "a,b,c\nHello,65,\"2.5";
|
||||
assertThrown!IncompleteCellException(text.csvReader.count);
|
||||
|
||||
// ignore the exceptions and try to handle invalid CSV
|
||||
auto firstLine = text.csvReader!(string, Malformed.ignore)(null).front;
|
||||
assert(firstLine.equal(["Hello", "65", "2.5"]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
string text = "76,26,22";
|
||||
auto records = text.csvReader!int;
|
||||
assert(records.equal!equal([
|
||||
[76, 26, 22],
|
||||
]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
string text = "Hello;65;2.5\nWorld;123;7.5";
|
||||
struct Layout
|
||||
{
|
||||
string name;
|
||||
int value;
|
||||
double other;
|
||||
}
|
||||
|
||||
auto records = text.csvReader!Layout(';');
|
||||
assert(records.equal([
|
||||
Layout("Hello", 65, 2.5),
|
||||
Layout("World", 123, 7.5),
|
||||
]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
string text = "A \" is now part of the data";
|
||||
auto records = text.csvReader!(string, Malformed.ignore);
|
||||
auto record = records.front;
|
||||
|
||||
assert(record.front == text);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
string text = "a,b,c\nHello,65,63.63\nWorld,123,3673.562";
|
||||
auto records = text.csvReader!int(["b"]);
|
||||
|
||||
assert(records.equal!equal([
|
||||
[65],
|
||||
[123],
|
||||
]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
string text = "a,b,c\nHello,65,2.5\nWorld,123,7.5";
|
||||
struct Layout
|
||||
{
|
||||
int value;
|
||||
double other;
|
||||
string name;
|
||||
}
|
||||
|
||||
auto records = text.csvReader!Layout(["b","c","a"]);
|
||||
assert(records.equal([
|
||||
Layout(65, 2.5, "Hello"),
|
||||
Layout(123, 7.5, "World")
|
||||
]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
string text = "a,b,c\nHello,65,63.63";
|
||||
auto records = text.csvReader(null);
|
||||
|
||||
assert(records.header == ["a","b","c"]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
string text = "76,26,22\n1,2\n3,4,5,6";
|
||||
auto records = text.csvReader!int(',', '"', true);
|
||||
|
||||
assert(records.equal!equal([
|
||||
[76, 26, 22],
|
||||
[1, 2],
|
||||
[3, 4, 5, 6]
|
||||
]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
static struct Three
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
int c;
|
||||
}
|
||||
|
||||
string text = "76,26,22\n1,2\n3,4,5,6";
|
||||
auto records = text.csvReader!Three(',', '"', true);
|
||||
|
||||
assert(records.equal([
|
||||
Three(76, 26, 22),
|
||||
Three(1, 2, 0),
|
||||
Three(3, 4, 5)
|
||||
]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
|
||||
auto text = "Name,Occupation,Salary\r" ~
|
||||
"Joe,Carpenter,300000\nFred,Blacksmith\r\n";
|
||||
|
||||
auto r = csvReader!(string[string])(text, null, ',', '"', true);
|
||||
|
||||
assert(r.equal([
|
||||
[ "Name" : "Joe", "Occupation" : "Carpenter", "Salary" : "300000" ],
|
||||
[ "Name" : "Fred", "Occupation" : "Blacksmith" ]
|
||||
]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.csv;
|
||||
|
||||
import std.array : appender;
|
||||
import std.range.primitives : popFront;
|
||||
|
||||
string str = "65,63\n123,3673";
|
||||
|
||||
auto a = appender!(char[])();
|
||||
|
||||
csvNextToken(str,a,',','"');
|
||||
assert(a.data == "65");
|
||||
assert(str == ",63\n123,3673");
|
||||
|
||||
str.popFront();
|
||||
a.shrinkTo(0);
|
||||
csvNextToken(str,a,',','"');
|
||||
assert(a.data == "63");
|
||||
assert(str == "\n123,3673");
|
||||
|
||||
str.popFront();
|
||||
a.shrinkTo(0);
|
||||
csvNextToken(str,a,',','"');
|
||||
assert(a.data == "123");
|
||||
assert(str == ",3673");
|
||||
}
|
||||
|
992
libphobos/testsuite/libphobos.phobos/std_datetime_date.d
Normal file
992
libphobos/testsuite/libphobos.phobos/std_datetime_date.d
Normal file
|
@ -0,0 +1,992 @@
|
|||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(2018, 10, 1).month == Month.oct);
|
||||
assert(DateTime(1, 1, 1).month == Month.jan);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(2018, 10, 1).dayOfWeek == DayOfWeek.mon);
|
||||
assert(DateTime(5, 5, 5).dayOfWeek == DayOfWeek.thu);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).year == 1999);
|
||||
assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).year == 2010);
|
||||
assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).year == -7);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(0, 1, 1), TimeOfDay(12, 30, 33)).yearBC == 1);
|
||||
assert(DateTime(Date(-1, 1, 1), TimeOfDay(10, 7, 2)).yearBC == 2);
|
||||
assert(DateTime(Date(-100, 1, 1), TimeOfDay(4, 59, 0)).yearBC == 101);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto dt = DateTime(Date(2010, 1, 1), TimeOfDay(7, 30, 0));
|
||||
dt.yearBC = 1;
|
||||
assert(dt == DateTime(Date(0, 1, 1), TimeOfDay(7, 30, 0)));
|
||||
|
||||
dt.yearBC = 10;
|
||||
assert(dt == DateTime(Date(-9, 1, 1), TimeOfDay(7, 30, 0)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).month == 7);
|
||||
assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).month == 10);
|
||||
assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).month == 4);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).day == 6);
|
||||
assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).day == 4);
|
||||
assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).day == 5);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto dt1 = DateTime(2010, 1, 1, 12, 30, 33);
|
||||
dt1.add!"months"(11);
|
||||
assert(dt1 == DateTime(2010, 12, 1, 12, 30, 33));
|
||||
|
||||
auto dt2 = DateTime(2010, 1, 1, 12, 30, 33);
|
||||
dt2.add!"months"(-11);
|
||||
assert(dt2 == DateTime(2009, 2, 1, 12, 30, 33));
|
||||
|
||||
auto dt3 = DateTime(2000, 2, 29, 12, 30, 33);
|
||||
dt3.add!"years"(1);
|
||||
assert(dt3 == DateTime(2001, 3, 1, 12, 30, 33));
|
||||
|
||||
auto dt4 = DateTime(2000, 2, 29, 12, 30, 33);
|
||||
dt4.add!"years"(1, AllowDayOverflow.no);
|
||||
assert(dt4 == DateTime(2001, 2, 28, 12, 30, 33));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto dt1 = DateTime(2010, 1, 1, 12, 33, 33);
|
||||
dt1.roll!"months"(1);
|
||||
assert(dt1 == DateTime(2010, 2, 1, 12, 33, 33));
|
||||
|
||||
auto dt2 = DateTime(2010, 1, 1, 12, 33, 33);
|
||||
dt2.roll!"months"(-1);
|
||||
assert(dt2 == DateTime(2010, 12, 1, 12, 33, 33));
|
||||
|
||||
auto dt3 = DateTime(1999, 1, 29, 12, 33, 33);
|
||||
dt3.roll!"months"(1);
|
||||
assert(dt3 == DateTime(1999, 3, 1, 12, 33, 33));
|
||||
|
||||
auto dt4 = DateTime(1999, 1, 29, 12, 33, 33);
|
||||
dt4.roll!"months"(1, AllowDayOverflow.no);
|
||||
assert(dt4 == DateTime(1999, 2, 28, 12, 33, 33));
|
||||
|
||||
auto dt5 = DateTime(2000, 2, 29, 12, 30, 33);
|
||||
dt5.roll!"years"(1);
|
||||
assert(dt5 == DateTime(2001, 3, 1, 12, 30, 33));
|
||||
|
||||
auto dt6 = DateTime(2000, 2, 29, 12, 30, 33);
|
||||
dt6.roll!"years"(1, AllowDayOverflow.no);
|
||||
assert(dt6 == DateTime(2001, 2, 28, 12, 30, 33));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto dt1 = DateTime(2010, 1, 1, 11, 23, 12);
|
||||
dt1.roll!"days"(1);
|
||||
assert(dt1 == DateTime(2010, 1, 2, 11, 23, 12));
|
||||
dt1.roll!"days"(365);
|
||||
assert(dt1 == DateTime(2010, 1, 26, 11, 23, 12));
|
||||
dt1.roll!"days"(-32);
|
||||
assert(dt1 == DateTime(2010, 1, 25, 11, 23, 12));
|
||||
|
||||
auto dt2 = DateTime(2010, 7, 4, 12, 0, 0);
|
||||
dt2.roll!"hours"(1);
|
||||
assert(dt2 == DateTime(2010, 7, 4, 13, 0, 0));
|
||||
|
||||
auto dt3 = DateTime(2010, 1, 1, 0, 0, 0);
|
||||
dt3.roll!"seconds"(-1);
|
||||
assert(dt3 == DateTime(2010, 1, 1, 0, 0, 59));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import core.time : hours, seconds;
|
||||
|
||||
assert(DateTime(2015, 12, 31, 23, 59, 59) + seconds(1) ==
|
||||
DateTime(2016, 1, 1, 0, 0, 0));
|
||||
|
||||
assert(DateTime(2015, 12, 31, 23, 59, 59) + hours(1) ==
|
||||
DateTime(2016, 1, 1, 0, 59, 59));
|
||||
|
||||
assert(DateTime(2016, 1, 1, 0, 0, 0) - seconds(1) ==
|
||||
DateTime(2015, 12, 31, 23, 59, 59));
|
||||
|
||||
assert(DateTime(2016, 1, 1, 0, 59, 59) - hours(1) ==
|
||||
DateTime(2015, 12, 31, 23, 59, 59));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(1999, 2, 1, 12, 2, 3).diffMonths(
|
||||
DateTime(1999, 1, 31, 23, 59, 59)) == 1);
|
||||
|
||||
assert(DateTime(1999, 1, 31, 0, 0, 0).diffMonths(
|
||||
DateTime(1999, 2, 1, 12, 3, 42)) == -1);
|
||||
|
||||
assert(DateTime(1999, 3, 1, 5, 30, 0).diffMonths(
|
||||
DateTime(1999, 1, 1, 2, 4, 7)) == 2);
|
||||
|
||||
assert(DateTime(1999, 1, 1, 7, 2, 4).diffMonths(
|
||||
DateTime(1999, 3, 31, 0, 30, 58)) == -2);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(1999, 1, 1), TimeOfDay(12, 22, 7)).dayOfYear == 1);
|
||||
assert(DateTime(Date(1999, 12, 31), TimeOfDay(7, 2, 59)).dayOfYear == 365);
|
||||
assert(DateTime(Date(2000, 12, 31), TimeOfDay(21, 20, 0)).dayOfYear == 366);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)).dayOfGregorianCal == 1);
|
||||
assert(DateTime(Date(1, 12, 31), TimeOfDay(23, 59, 59)).dayOfGregorianCal == 365);
|
||||
assert(DateTime(Date(2, 1, 1), TimeOfDay(2, 2, 2)).dayOfGregorianCal == 366);
|
||||
|
||||
assert(DateTime(Date(0, 12, 31), TimeOfDay(7, 7, 7)).dayOfGregorianCal == 0);
|
||||
assert(DateTime(Date(0, 1, 1), TimeOfDay(19, 30, 0)).dayOfGregorianCal == -365);
|
||||
assert(DateTime(Date(-1, 12, 31), TimeOfDay(4, 7, 0)).dayOfGregorianCal == -366);
|
||||
|
||||
assert(DateTime(Date(2000, 1, 1), TimeOfDay(9, 30, 20)).dayOfGregorianCal == 730_120);
|
||||
assert(DateTime(Date(2010, 12, 31), TimeOfDay(15, 45, 50)).dayOfGregorianCal == 734_137);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto dt = DateTime(Date.init, TimeOfDay(12, 0, 0));
|
||||
dt.dayOfGregorianCal = 1;
|
||||
assert(dt == DateTime(Date(1, 1, 1), TimeOfDay(12, 0, 0)));
|
||||
|
||||
dt.dayOfGregorianCal = 365;
|
||||
assert(dt == DateTime(Date(1, 12, 31), TimeOfDay(12, 0, 0)));
|
||||
|
||||
dt.dayOfGregorianCal = 366;
|
||||
assert(dt == DateTime(Date(2, 1, 1), TimeOfDay(12, 0, 0)));
|
||||
|
||||
dt.dayOfGregorianCal = 0;
|
||||
assert(dt == DateTime(Date(0, 12, 31), TimeOfDay(12, 0, 0)));
|
||||
|
||||
dt.dayOfGregorianCal = -365;
|
||||
assert(dt == DateTime(Date(-0, 1, 1), TimeOfDay(12, 0, 0)));
|
||||
|
||||
dt.dayOfGregorianCal = -366;
|
||||
assert(dt == DateTime(Date(-1, 12, 31), TimeOfDay(12, 0, 0)));
|
||||
|
||||
dt.dayOfGregorianCal = 730_120;
|
||||
assert(dt == DateTime(Date(2000, 1, 1), TimeOfDay(12, 0, 0)));
|
||||
|
||||
dt.dayOfGregorianCal = 734_137;
|
||||
assert(dt == DateTime(Date(2010, 12, 31), TimeOfDay(12, 0, 0)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).endOfMonth ==
|
||||
DateTime(Date(1999, 1, 31), TimeOfDay(23, 59, 59)));
|
||||
|
||||
assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).endOfMonth ==
|
||||
DateTime(Date(1999, 2, 28), TimeOfDay(23, 59, 59)));
|
||||
|
||||
assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).endOfMonth ==
|
||||
DateTime(Date(2000, 2, 29), TimeOfDay(23, 59, 59)));
|
||||
|
||||
assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).endOfMonth ==
|
||||
DateTime(Date(2000, 6, 30), TimeOfDay(23, 59, 59)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).daysInMonth == 31);
|
||||
assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).daysInMonth == 28);
|
||||
assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).daysInMonth == 29);
|
||||
assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).daysInMonth == 30);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(1, 1, 1), TimeOfDay(12, 7, 0)).isAD);
|
||||
assert(DateTime(Date(2010, 12, 31), TimeOfDay(0, 0, 0)).isAD);
|
||||
assert(!DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 59)).isAD);
|
||||
assert(!DateTime(Date(-2010, 1, 1), TimeOfDay(2, 2, 2)).isAD);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOString() ==
|
||||
"20100704T070612");
|
||||
|
||||
assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOString() ==
|
||||
"19981225T021500");
|
||||
|
||||
assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOString() ==
|
||||
"00000105T230959");
|
||||
|
||||
assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOString() ==
|
||||
"-00040105T000002");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOExtString() ==
|
||||
"2010-07-04T07:06:12");
|
||||
|
||||
assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOExtString() ==
|
||||
"1998-12-25T02:15:00");
|
||||
|
||||
assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOExtString() ==
|
||||
"0000-01-05T23:09:59");
|
||||
|
||||
assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOExtString() ==
|
||||
"-0004-01-05T00:00:02");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toSimpleString() ==
|
||||
"2010-Jul-04 07:06:12");
|
||||
|
||||
assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toSimpleString() ==
|
||||
"1998-Dec-25 02:15:00");
|
||||
|
||||
assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toSimpleString() ==
|
||||
"0000-Jan-05 23:09:59");
|
||||
|
||||
assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toSimpleString() ==
|
||||
"-0004-Jan-05 00:00:02");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime.fromISOString("20100704T070612") ==
|
||||
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
|
||||
|
||||
assert(DateTime.fromISOString("19981225T021500") ==
|
||||
DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
|
||||
|
||||
assert(DateTime.fromISOString("00000105T230959") ==
|
||||
DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
|
||||
|
||||
assert(DateTime.fromISOString("-00040105T000002") ==
|
||||
DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
|
||||
|
||||
assert(DateTime.fromISOString(" 20100704T070612 ") ==
|
||||
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime.fromISOExtString("2010-07-04T07:06:12") ==
|
||||
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
|
||||
|
||||
assert(DateTime.fromISOExtString("1998-12-25T02:15:00") ==
|
||||
DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
|
||||
|
||||
assert(DateTime.fromISOExtString("0000-01-05T23:09:59") ==
|
||||
DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
|
||||
|
||||
assert(DateTime.fromISOExtString("-0004-01-05T00:00:02") ==
|
||||
DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
|
||||
|
||||
assert(DateTime.fromISOExtString(" 2010-07-04T07:06:12 ") ==
|
||||
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(DateTime.fromSimpleString("2010-Jul-04 07:06:12") ==
|
||||
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
|
||||
assert(DateTime.fromSimpleString("1998-Dec-25 02:15:00") ==
|
||||
DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
|
||||
assert(DateTime.fromSimpleString("0000-Jan-05 23:09:59") ==
|
||||
DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
|
||||
assert(DateTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
|
||||
DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
|
||||
assert(DateTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
|
||||
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
|
||||
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import core.time : days, seconds;
|
||||
|
||||
auto dt = DateTime(2000, 6, 1, 10, 30, 0);
|
||||
|
||||
assert(dt.date == Date(2000, 6, 1));
|
||||
assert(dt.timeOfDay == TimeOfDay(10, 30, 0));
|
||||
assert(dt.dayOfYear == 153);
|
||||
assert(dt.dayOfWeek == DayOfWeek.thu);
|
||||
|
||||
dt += 10.days + 100.seconds;
|
||||
assert(dt == DateTime(2000, 6, 11, 10, 31, 40));
|
||||
|
||||
assert(dt.toISOExtString() == "2000-06-11T10:31:40");
|
||||
assert(dt.toISOString() == "20000611T103140");
|
||||
assert(dt.toSimpleString() == "2000-Jun-11 10:31:40");
|
||||
|
||||
assert(DateTime.fromISOExtString("2018-01-01T12:00:00") == DateTime(2018, 1, 1, 12, 0, 0));
|
||||
assert(DateTime.fromISOString("20180101T120000") == DateTime(2018, 1, 1, 12, 0, 0));
|
||||
assert(DateTime.fromSimpleString("2018-Jan-01 12:00:00") == DateTime(2018, 1, 1, 12, 0, 0));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1999, 7, 6).year == 1999);
|
||||
assert(Date(2010, 10, 4).year == 2010);
|
||||
assert(Date(-7, 4, 5).year == -7);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1999, 7, 6).year == 1999);
|
||||
assert(Date(2010, 10, 4).year == 2010);
|
||||
assert(Date(-7, 4, 5).year == -7);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(0, 1, 1).yearBC == 1);
|
||||
assert(Date(-1, 1, 1).yearBC == 2);
|
||||
assert(Date(-100, 1, 1).yearBC == 101);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto date = Date(2010, 1, 1);
|
||||
date.yearBC = 1;
|
||||
assert(date == Date(0, 1, 1));
|
||||
|
||||
date.yearBC = 10;
|
||||
assert(date == Date(-9, 1, 1));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1999, 7, 6).month == 7);
|
||||
assert(Date(2010, 10, 4).month == 10);
|
||||
assert(Date(-7, 4, 5).month == 4);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1999, 7, 6).day == 6);
|
||||
assert(Date(2010, 10, 4).day == 4);
|
||||
assert(Date(-7, 4, 5).day == 5);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto d1 = Date(2010, 1, 1);
|
||||
d1.add!"months"(11);
|
||||
assert(d1 == Date(2010, 12, 1));
|
||||
|
||||
auto d2 = Date(2010, 1, 1);
|
||||
d2.add!"months"(-11);
|
||||
assert(d2 == Date(2009, 2, 1));
|
||||
|
||||
auto d3 = Date(2000, 2, 29);
|
||||
d3.add!"years"(1);
|
||||
assert(d3 == Date(2001, 3, 1));
|
||||
|
||||
auto d4 = Date(2000, 2, 29);
|
||||
d4.add!"years"(1, AllowDayOverflow.no);
|
||||
assert(d4 == Date(2001, 2, 28));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto d1 = Date(2010, 1, 1);
|
||||
d1.roll!"months"(1);
|
||||
assert(d1 == Date(2010, 2, 1));
|
||||
|
||||
auto d2 = Date(2010, 1, 1);
|
||||
d2.roll!"months"(-1);
|
||||
assert(d2 == Date(2010, 12, 1));
|
||||
|
||||
auto d3 = Date(1999, 1, 29);
|
||||
d3.roll!"months"(1);
|
||||
assert(d3 == Date(1999, 3, 1));
|
||||
|
||||
auto d4 = Date(1999, 1, 29);
|
||||
d4.roll!"months"(1, AllowDayOverflow.no);
|
||||
assert(d4 == Date(1999, 2, 28));
|
||||
|
||||
auto d5 = Date(2000, 2, 29);
|
||||
d5.roll!"years"(1);
|
||||
assert(d5 == Date(2001, 3, 1));
|
||||
|
||||
auto d6 = Date(2000, 2, 29);
|
||||
d6.roll!"years"(1, AllowDayOverflow.no);
|
||||
assert(d6 == Date(2001, 2, 28));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto d = Date(2010, 1, 1);
|
||||
d.roll!"days"(1);
|
||||
assert(d == Date(2010, 1, 2));
|
||||
d.roll!"days"(365);
|
||||
assert(d == Date(2010, 1, 26));
|
||||
d.roll!"days"(-32);
|
||||
assert(d == Date(2010, 1, 25));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import core.time : days;
|
||||
|
||||
assert(Date(2015, 12, 31) + days(1) == Date(2016, 1, 1));
|
||||
assert(Date(2004, 2, 26) + days(4) == Date(2004, 3, 1));
|
||||
|
||||
assert(Date(2016, 1, 1) - days(1) == Date(2015, 12, 31));
|
||||
assert(Date(2004, 3, 1) - days(4) == Date(2004, 2, 26));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1999, 2, 1).diffMonths(Date(1999, 1, 31)) == 1);
|
||||
assert(Date(1999, 1, 31).diffMonths(Date(1999, 2, 1)) == -1);
|
||||
assert(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)) == 2);
|
||||
assert(Date(1999, 1, 1).diffMonths(Date(1999, 3, 31)) == -2);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1999, 1, 1).dayOfYear == 1);
|
||||
assert(Date(1999, 12, 31).dayOfYear == 365);
|
||||
assert(Date(2000, 12, 31).dayOfYear == 366);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1, 1, 1).dayOfGregorianCal == 1);
|
||||
assert(Date(1, 12, 31).dayOfGregorianCal == 365);
|
||||
assert(Date(2, 1, 1).dayOfGregorianCal == 366);
|
||||
|
||||
assert(Date(0, 12, 31).dayOfGregorianCal == 0);
|
||||
assert(Date(0, 1, 1).dayOfGregorianCal == -365);
|
||||
assert(Date(-1, 12, 31).dayOfGregorianCal == -366);
|
||||
|
||||
assert(Date(2000, 1, 1).dayOfGregorianCal == 730_120);
|
||||
assert(Date(2010, 12, 31).dayOfGregorianCal == 734_137);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto date = Date.init;
|
||||
date.dayOfGregorianCal = 1;
|
||||
assert(date == Date(1, 1, 1));
|
||||
|
||||
date.dayOfGregorianCal = 365;
|
||||
assert(date == Date(1, 12, 31));
|
||||
|
||||
date.dayOfGregorianCal = 366;
|
||||
assert(date == Date(2, 1, 1));
|
||||
|
||||
date.dayOfGregorianCal = 0;
|
||||
assert(date == Date(0, 12, 31));
|
||||
|
||||
date.dayOfGregorianCal = -365;
|
||||
assert(date == Date(-0, 1, 1));
|
||||
|
||||
date.dayOfGregorianCal = -366;
|
||||
assert(date == Date(-1, 12, 31));
|
||||
|
||||
date.dayOfGregorianCal = 730_120;
|
||||
assert(date == Date(2000, 1, 1));
|
||||
|
||||
date.dayOfGregorianCal = 734_137;
|
||||
assert(date == Date(2010, 12, 31));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1999, 1, 6).endOfMonth == Date(1999, 1, 31));
|
||||
assert(Date(1999, 2, 7).endOfMonth == Date(1999, 2, 28));
|
||||
assert(Date(2000, 2, 7).endOfMonth == Date(2000, 2, 29));
|
||||
assert(Date(2000, 6, 4).endOfMonth == Date(2000, 6, 30));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1999, 1, 6).daysInMonth == 31);
|
||||
assert(Date(1999, 2, 7).daysInMonth == 28);
|
||||
assert(Date(2000, 2, 7).daysInMonth == 29);
|
||||
assert(Date(2000, 6, 4).daysInMonth == 30);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(1, 1, 1).isAD);
|
||||
assert(Date(2010, 12, 31).isAD);
|
||||
assert(!Date(0, 12, 31).isAD);
|
||||
assert(!Date(-2010, 1, 1).isAD);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(2010, 7, 4).toISOString() == "20100704");
|
||||
assert(Date(1998, 12, 25).toISOString() == "19981225");
|
||||
assert(Date(0, 1, 5).toISOString() == "00000105");
|
||||
assert(Date(-4, 1, 5).toISOString() == "-00040105");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(2010, 7, 4).toISOExtString() == "2010-07-04");
|
||||
assert(Date(1998, 12, 25).toISOExtString() == "1998-12-25");
|
||||
assert(Date(0, 1, 5).toISOExtString() == "0000-01-05");
|
||||
assert(Date(-4, 1, 5).toISOExtString() == "-0004-01-05");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date(2010, 7, 4).toSimpleString() == "2010-Jul-04");
|
||||
assert(Date(1998, 12, 25).toSimpleString() == "1998-Dec-25");
|
||||
assert(Date(0, 1, 5).toSimpleString() == "0000-Jan-05");
|
||||
assert(Date(-4, 1, 5).toSimpleString() == "-0004-Jan-05");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date.fromISOString("20100704") == Date(2010, 7, 4));
|
||||
assert(Date.fromISOString("19981225") == Date(1998, 12, 25));
|
||||
assert(Date.fromISOString("00000105") == Date(0, 1, 5));
|
||||
assert(Date.fromISOString("-00040105") == Date(-4, 1, 5));
|
||||
assert(Date.fromISOString(" 20100704 ") == Date(2010, 7, 4));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date.fromISOExtString("2010-07-04") == Date(2010, 7, 4));
|
||||
assert(Date.fromISOExtString("1998-12-25") == Date(1998, 12, 25));
|
||||
assert(Date.fromISOExtString("0000-01-05") == Date(0, 1, 5));
|
||||
assert(Date.fromISOExtString("-0004-01-05") == Date(-4, 1, 5));
|
||||
assert(Date.fromISOExtString(" 2010-07-04 ") == Date(2010, 7, 4));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(Date.fromSimpleString("2010-Jul-04") == Date(2010, 7, 4));
|
||||
assert(Date.fromSimpleString("1998-Dec-25") == Date(1998, 12, 25));
|
||||
assert(Date.fromSimpleString("0000-Jan-05") == Date(0, 1, 5));
|
||||
assert(Date.fromSimpleString("-0004-Jan-05") == Date(-4, 1, 5));
|
||||
assert(Date.fromSimpleString(" 2010-Jul-04 ") == Date(2010, 7, 4));
|
||||
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import core.time : days;
|
||||
|
||||
auto d = Date(2000, 6, 1);
|
||||
|
||||
assert(d.dayOfYear == 153);
|
||||
assert(d.dayOfWeek == DayOfWeek.thu);
|
||||
|
||||
d += 10.days;
|
||||
assert(d == Date(2000, 6, 11));
|
||||
|
||||
assert(d.toISOExtString() == "2000-06-11");
|
||||
assert(d.toISOString() == "20000611");
|
||||
assert(d.toSimpleString() == "2000-Jun-11");
|
||||
|
||||
assert(Date.fromISOExtString("2018-01-01") == Date(2018, 1, 1));
|
||||
assert(Date.fromISOString("20180101") == Date(2018, 1, 1));
|
||||
assert(Date.fromSimpleString("2018-Jan-01") == Date(2018, 1, 1));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
auto tod1 = TimeOfDay(7, 12, 0);
|
||||
tod1.roll!"hours"(1);
|
||||
assert(tod1 == TimeOfDay(8, 12, 0));
|
||||
|
||||
auto tod2 = TimeOfDay(7, 12, 0);
|
||||
tod2.roll!"hours"(-1);
|
||||
assert(tod2 == TimeOfDay(6, 12, 0));
|
||||
|
||||
auto tod3 = TimeOfDay(23, 59, 0);
|
||||
tod3.roll!"minutes"(1);
|
||||
assert(tod3 == TimeOfDay(23, 0, 0));
|
||||
|
||||
auto tod4 = TimeOfDay(0, 0, 0);
|
||||
tod4.roll!"minutes"(-1);
|
||||
assert(tod4 == TimeOfDay(0, 59, 0));
|
||||
|
||||
auto tod5 = TimeOfDay(23, 59, 59);
|
||||
tod5.roll!"seconds"(1);
|
||||
assert(tod5 == TimeOfDay(23, 59, 0));
|
||||
|
||||
auto tod6 = TimeOfDay(0, 0, 0);
|
||||
tod6.roll!"seconds"(-1);
|
||||
assert(tod6 == TimeOfDay(0, 0, 59));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import core.time : hours, minutes, seconds;
|
||||
|
||||
assert(TimeOfDay(12, 12, 12) + seconds(1) == TimeOfDay(12, 12, 13));
|
||||
assert(TimeOfDay(12, 12, 12) + minutes(1) == TimeOfDay(12, 13, 12));
|
||||
assert(TimeOfDay(12, 12, 12) + hours(1) == TimeOfDay(13, 12, 12));
|
||||
assert(TimeOfDay(23, 59, 59) + seconds(1) == TimeOfDay(0, 0, 0));
|
||||
|
||||
assert(TimeOfDay(12, 12, 12) - seconds(1) == TimeOfDay(12, 12, 11));
|
||||
assert(TimeOfDay(12, 12, 12) - minutes(1) == TimeOfDay(12, 11, 12));
|
||||
assert(TimeOfDay(12, 12, 12) - hours(1) == TimeOfDay(11, 12, 12));
|
||||
assert(TimeOfDay(0, 0, 0) - seconds(1) == TimeOfDay(23, 59, 59));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(TimeOfDay(0, 0, 0).toISOString() == "000000");
|
||||
assert(TimeOfDay(12, 30, 33).toISOString() == "123033");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(TimeOfDay(0, 0, 0).toISOExtString() == "00:00:00");
|
||||
assert(TimeOfDay(12, 30, 33).toISOExtString() == "12:30:33");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(TimeOfDay.fromISOString("000000") == TimeOfDay(0, 0, 0));
|
||||
assert(TimeOfDay.fromISOString("123033") == TimeOfDay(12, 30, 33));
|
||||
assert(TimeOfDay.fromISOString(" 123033 ") == TimeOfDay(12, 30, 33));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(TimeOfDay.fromISOExtString("00:00:00") == TimeOfDay(0, 0, 0));
|
||||
assert(TimeOfDay.fromISOExtString("12:30:33") == TimeOfDay(12, 30, 33));
|
||||
assert(TimeOfDay.fromISOExtString(" 12:30:33 ") == TimeOfDay(12, 30, 33));
|
||||
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import core.time : minutes, seconds;
|
||||
|
||||
auto t = TimeOfDay(12, 30, 0);
|
||||
|
||||
t += 10.minutes + 100.seconds;
|
||||
assert(t == TimeOfDay(12, 41, 40));
|
||||
|
||||
assert(t.toISOExtString() == "12:41:40");
|
||||
assert(t.toISOString() == "124140");
|
||||
|
||||
assert(TimeOfDay.fromISOExtString("15:00:00") == TimeOfDay(15, 0, 0));
|
||||
assert(TimeOfDay.fromISOString("015000") == TimeOfDay(1, 50, 0));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(valid!"hours"(12));
|
||||
assert(!valid!"hours"(32));
|
||||
assert(valid!"months"(12));
|
||||
assert(!valid!"months"(13));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(valid!"days"(2016, 2, 29));
|
||||
assert(!valid!"days"(2016, 2, 30));
|
||||
assert(valid!"days"(2017, 2, 20));
|
||||
assert(!valid!"days"(2017, 2, 29));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import std.exception : assertThrown, assertNotThrown;
|
||||
|
||||
assertNotThrown(enforceValid!"months"(10));
|
||||
assertNotThrown(enforceValid!"seconds"(40));
|
||||
|
||||
assertThrown!DateTimeException(enforceValid!"months"(0));
|
||||
assertThrown!DateTimeException(enforceValid!"hours"(24));
|
||||
assertThrown!DateTimeException(enforceValid!"minutes"(60));
|
||||
assertThrown!DateTimeException(enforceValid!"seconds"(60));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import std.exception : assertThrown, assertNotThrown;
|
||||
|
||||
assertNotThrown(enforceValid!"days"(2000, Month.jan, 1));
|
||||
// leap year
|
||||
assertNotThrown(enforceValid!"days"(2000, Month.feb, 29));
|
||||
|
||||
assertThrown!DateTimeException(enforceValid!"days"(2001, Month.feb, 29));
|
||||
assertThrown!DateTimeException(enforceValid!"days"(2000, Month.jan, 32));
|
||||
assertThrown!DateTimeException(enforceValid!"days"(2000, Month.apr, 31));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.mon) == 0);
|
||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.sun) == 6);
|
||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.wed) == 2);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(monthsToMonth(Month.jan, Month.jan) == 0);
|
||||
assert(monthsToMonth(Month.jan, Month.dec) == 11);
|
||||
assert(monthsToMonth(Month.jul, Month.oct) == 3);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
foreach (year; [1, 2, 100, 2001, 2002, 2003, 2005, 2006, 2007, 2009, 2010])
|
||||
{
|
||||
assert(!yearIsLeapYear(year));
|
||||
assert(!yearIsLeapYear(-year));
|
||||
}
|
||||
|
||||
foreach (year; [0, 4, 8, 400, 800, 1600, 1996, 2000, 2004, 2008, 2012])
|
||||
{
|
||||
assert(yearIsLeapYear(year));
|
||||
assert(yearIsLeapYear(-year));
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import core.time : Duration;
|
||||
import std.datetime.interval : Interval;
|
||||
import std.datetime.systime : SysTime;
|
||||
|
||||
static assert(isTimePoint!Date);
|
||||
static assert(isTimePoint!DateTime);
|
||||
static assert(isTimePoint!SysTime);
|
||||
static assert(isTimePoint!TimeOfDay);
|
||||
|
||||
static assert(!isTimePoint!int);
|
||||
static assert(!isTimePoint!Duration);
|
||||
static assert(!isTimePoint!(Interval!SysTime));
|
||||
}
|
||||
|
||||
@safe @nogc nothrow unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
assert(validTimeUnits("msecs", "seconds", "minutes"));
|
||||
assert(validTimeUnits("days", "weeks", "months"));
|
||||
assert(!validTimeUnits("ms", "seconds", "minutes"));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
assert(cmpTimeUnits("hours", "hours") == 0);
|
||||
assert(cmpTimeUnits("hours", "weeks") < 0);
|
||||
assert(cmpTimeUnits("months", "seconds") > 0);
|
||||
|
||||
assertThrown!DateTimeException(cmpTimeUnits("month", "second"));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.datetime.date;
|
||||
|
||||
static assert(CmpTimeUnits!("years", "weeks") > 0);
|
||||
static assert(CmpTimeUnits!("days", "days") == 0);
|
||||
static assert(CmpTimeUnits!("seconds", "hours") < 0);
|
||||
}
|
||||
|
112
libphobos/testsuite/libphobos.phobos/std_datetime_interval.d
Normal file
112
libphobos/testsuite/libphobos.phobos/std_datetime_interval.d
Normal file
|
@ -0,0 +1,112 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.datetime.interval;
|
||||
|
||||
import std.datetime.date : Date, DayOfWeek;
|
||||
|
||||
auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
|
||||
auto func = everyDayOfWeek!Date(DayOfWeek.mon);
|
||||
auto range = interval.fwdRange(func);
|
||||
|
||||
// A Thursday. Using PopFirst.yes would have made this Date(2010, 9, 6).
|
||||
assert(range.front == Date(2010, 9, 2));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2010, 9, 6));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2010, 9, 13));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2010, 9, 20));
|
||||
|
||||
range.popFront();
|
||||
assert(range.empty);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.datetime.interval;
|
||||
|
||||
import std.datetime.date : Date, Month;
|
||||
|
||||
auto interval = Interval!Date(Date(2000, 1, 30), Date(2004, 8, 5));
|
||||
auto func = everyMonth!Date(Month.feb);
|
||||
auto range = interval.fwdRange(func);
|
||||
|
||||
// Using PopFirst.yes would have made this Date(2010, 2, 29).
|
||||
assert(range.front == Date(2000, 1, 30));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2000, 2, 29));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2001, 2, 28));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2002, 2, 28));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2003, 2, 28));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2004, 2, 28));
|
||||
|
||||
range.popFront();
|
||||
assert(range.empty);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.datetime.interval;
|
||||
|
||||
import core.time : dur;
|
||||
import std.datetime.date : Date;
|
||||
|
||||
auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
|
||||
auto func = everyDuration!Date(dur!"days"(8));
|
||||
auto range = interval.fwdRange(func);
|
||||
|
||||
// Using PopFirst.yes would have made this Date(2010, 9, 10).
|
||||
assert(range.front == Date(2010, 9, 2));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2010, 9, 10));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2010, 9, 18));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2010, 9, 26));
|
||||
|
||||
range.popFront();
|
||||
assert(range.empty);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.datetime.interval;
|
||||
|
||||
import core.time : dur;
|
||||
import std.datetime.date : AllowDayOverflow, Date;
|
||||
|
||||
auto interval = Interval!Date(Date(2010, 9, 2), Date(2025, 9, 27));
|
||||
auto func = everyDuration!Date(4, 1, AllowDayOverflow.yes, dur!"days"(2));
|
||||
auto range = interval.fwdRange(func);
|
||||
|
||||
// Using PopFirst.yes would have made this Date(2014, 10, 12).
|
||||
assert(range.front == Date(2010, 9, 2));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2014, 10, 4));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2018, 11, 6));
|
||||
|
||||
range.popFront();
|
||||
assert(range.front == Date(2022, 12, 8));
|
||||
|
||||
range.popFront();
|
||||
assert(range.empty);
|
||||
}
|
||||
|
34
libphobos/testsuite/libphobos.phobos/std_datetime_package.d
Normal file
34
libphobos/testsuite/libphobos.phobos/std_datetime_package.d
Normal file
|
@ -0,0 +1,34 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.datetime;
|
||||
|
||||
import std.datetime.systime : SysTime, Clock;
|
||||
|
||||
SysTime currentTime = Clock.currTime();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime;
|
||||
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
auto dt = DateTime(2018, 1, 1, 12, 30, 10);
|
||||
assert(dt.toISOString() == "20180101T123010");
|
||||
assert(dt.toISOExtString() == "2018-01-01T12:30:10");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime;
|
||||
|
||||
import std.datetime.systime : SysTime;
|
||||
import std.datetime.timezone : UTC;
|
||||
import core.time : days;
|
||||
|
||||
auto st = SysTime(DateTime(2018, 1, 1, 12, 30, 10), UTC());
|
||||
assert(st.toISOExtString() == "2018-01-01T12:30:10Z");
|
||||
st += 2.days;
|
||||
assert(st.toISOExtString() == "2018-01-03T12:30:10Z");
|
||||
}
|
||||
|
210
libphobos/testsuite/libphobos.phobos/std_datetime_stopwatch.d
Normal file
210
libphobos/testsuite/libphobos.phobos/std_datetime_stopwatch.d
Normal file
|
@ -0,0 +1,210 @@
|
|||
@system nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
import core.thread : Thread;
|
||||
|
||||
{
|
||||
auto sw = StopWatch(AutoStart.yes);
|
||||
assert(sw.running);
|
||||
Thread.sleep(usecs(1));
|
||||
assert(sw.peek() > Duration.zero);
|
||||
}
|
||||
{
|
||||
auto sw = StopWatch(AutoStart.no);
|
||||
assert(!sw.running);
|
||||
Thread.sleep(usecs(1));
|
||||
assert(sw.peek() == Duration.zero);
|
||||
}
|
||||
{
|
||||
StopWatch sw;
|
||||
assert(!sw.running);
|
||||
Thread.sleep(usecs(1));
|
||||
assert(sw.peek() == Duration.zero);
|
||||
}
|
||||
|
||||
assert(StopWatch.init == StopWatch(AutoStart.no));
|
||||
assert(StopWatch.init != StopWatch(AutoStart.yes));
|
||||
|
||||
}
|
||||
|
||||
@system nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
import core.thread : Thread;
|
||||
|
||||
auto sw = StopWatch(AutoStart.yes);
|
||||
Thread.sleep(usecs(1));
|
||||
sw.stop();
|
||||
assert(sw.peek() > Duration.zero);
|
||||
sw.reset();
|
||||
assert(sw.peek() == Duration.zero);
|
||||
|
||||
}
|
||||
|
||||
@system nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
import core.thread : Thread;
|
||||
|
||||
StopWatch sw;
|
||||
assert(!sw.running);
|
||||
assert(sw.peek() == Duration.zero);
|
||||
sw.start();
|
||||
assert(sw.running);
|
||||
Thread.sleep(usecs(1));
|
||||
assert(sw.peek() > Duration.zero);
|
||||
|
||||
}
|
||||
|
||||
@system nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
import core.thread : Thread;
|
||||
|
||||
auto sw = StopWatch(AutoStart.yes);
|
||||
assert(sw.running);
|
||||
Thread.sleep(usecs(1));
|
||||
immutable t1 = sw.peek();
|
||||
assert(t1 > Duration.zero);
|
||||
|
||||
sw.stop();
|
||||
assert(!sw.running);
|
||||
immutable t2 = sw.peek();
|
||||
assert(t2 >= t1);
|
||||
immutable t3 = sw.peek();
|
||||
assert(t2 == t3);
|
||||
|
||||
}
|
||||
|
||||
@system nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
import core.thread : Thread;
|
||||
|
||||
auto sw = StopWatch(AutoStart.no);
|
||||
assert(sw.peek() == Duration.zero);
|
||||
sw.start();
|
||||
|
||||
Thread.sleep(usecs(1));
|
||||
assert(sw.peek() >= usecs(1));
|
||||
|
||||
Thread.sleep(usecs(1));
|
||||
assert(sw.peek() >= usecs(2));
|
||||
|
||||
sw.stop();
|
||||
immutable stopped = sw.peek();
|
||||
Thread.sleep(usecs(1));
|
||||
assert(sw.peek() == stopped);
|
||||
|
||||
sw.start();
|
||||
Thread.sleep(usecs(1));
|
||||
assert(sw.peek() > stopped);
|
||||
|
||||
}
|
||||
|
||||
@system nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
import core.thread : Thread;
|
||||
|
||||
StopWatch sw;
|
||||
sw.setTimeElapsed(hours(1));
|
||||
|
||||
// As discussed in MonoTime's documentation, converting between
|
||||
// Duration and ticks is not exact, though it will be close.
|
||||
// How exact it is depends on the frequency/resolution of the
|
||||
// system's monotonic clock.
|
||||
assert(abs(sw.peek() - hours(1)) < usecs(1));
|
||||
|
||||
sw.start();
|
||||
Thread.sleep(usecs(1));
|
||||
assert(sw.peek() > hours(1) + usecs(1));
|
||||
|
||||
}
|
||||
|
||||
@safe nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
StopWatch sw;
|
||||
assert(!sw.running);
|
||||
sw.start();
|
||||
assert(sw.running);
|
||||
sw.stop();
|
||||
assert(!sw.running);
|
||||
|
||||
}
|
||||
|
||||
@safe nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
auto sw = StopWatch(AutoStart.no);
|
||||
sw.start();
|
||||
// ... Insert operations to be timed here ...
|
||||
sw.stop();
|
||||
|
||||
long msecs = sw.peek.total!"msecs";
|
||||
long usecs = sw.peek.total!"usecs";
|
||||
long nsecs = sw.peek.total!"nsecs";
|
||||
|
||||
assert(usecs >= msecs * 1000);
|
||||
assert(nsecs >= usecs * 1000);
|
||||
}
|
||||
|
||||
@system nothrow @nogc unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
import core.thread : Thread;
|
||||
|
||||
auto sw = StopWatch(AutoStart.yes);
|
||||
|
||||
Duration t1 = sw.peek();
|
||||
Thread.sleep(usecs(1));
|
||||
Duration t2 = sw.peek();
|
||||
assert(t2 > t1);
|
||||
|
||||
Thread.sleep(usecs(1));
|
||||
sw.stop();
|
||||
|
||||
Duration t3 = sw.peek();
|
||||
assert(t3 > t2);
|
||||
Duration t4 = sw.peek();
|
||||
assert(t3 == t4);
|
||||
|
||||
sw.start();
|
||||
Thread.sleep(usecs(1));
|
||||
|
||||
Duration t5 = sw.peek();
|
||||
assert(t5 > t4);
|
||||
|
||||
// If stopping or resetting the StopWatch is not required, then
|
||||
// MonoTime can easily be used by itself without StopWatch.
|
||||
auto before = MonoTime.currTime;
|
||||
// do stuff...
|
||||
auto timeElapsed = MonoTime.currTime - before;
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.stopwatch;
|
||||
|
||||
import std.conv : to;
|
||||
|
||||
int a;
|
||||
void f0() {}
|
||||
void f1() { auto b = a; }
|
||||
void f2() { auto b = to!string(a); }
|
||||
auto r = benchmark!(f0, f1, f2)(10_000);
|
||||
Duration f0Result = r[0]; // time f0 took to run 10,000 times
|
||||
Duration f1Result = r[1]; // time f1 took to run 10,000 times
|
||||
Duration f2Result = r[2]; // time f2 took to run 10,000 times
|
||||
}
|
||||
|
750
libphobos/testsuite/libphobos.phobos/std_datetime_systime.d
Normal file
750
libphobos/testsuite/libphobos.phobos/std_datetime_systime.d
Normal file
|
@ -0,0 +1,750 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.timezone : LocalTime;
|
||||
SysTime today = Clock.currTime();
|
||||
assert(today.timezone is LocalTime());
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.date : DateTime;
|
||||
import std.datetime.timezone : UTC;
|
||||
|
||||
auto st = SysTime.fromISOExtString("2018-01-01T10:30:00Z");
|
||||
assert(st == SysTime(DateTime(2018, 1, 1, 10, 30, 0), UTC()));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : hours;
|
||||
import std.datetime.date : DateTime;
|
||||
import std.datetime.timezone : SimpleTimeZone;
|
||||
|
||||
auto ny = SysTime(
|
||||
DateTime(2018, 1, 1, 10, 30, 0),
|
||||
new immutable SimpleTimeZone(-5.hours, "America/New_York")
|
||||
);
|
||||
|
||||
// ISO standard time strings
|
||||
assert(ny.toISOString() == "20180101T103000-05:00");
|
||||
assert(ny.toISOExtString() == "2018-01-01T10:30:00-05:00");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.timezone : LocalTime;
|
||||
SysTime today = Clock.currTime();
|
||||
assert(today.timezone is LocalTime());
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).year == 1999);
|
||||
assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).year == 2010);
|
||||
assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).year == -7);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(0, 1, 1, 12, 30, 33)).yearBC == 1);
|
||||
assert(SysTime(DateTime(-1, 1, 1, 10, 7, 2)).yearBC == 2);
|
||||
assert(SysTime(DateTime(-100, 1, 1, 4, 59, 0)).yearBC == 101);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).month == 7);
|
||||
assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).month == 10);
|
||||
assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).month == 4);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).day == 6);
|
||||
assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).day == 4);
|
||||
assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).day == 5);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : msecs, usecs, hnsecs, nsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
auto dt = DateTime(1982, 4, 1, 20, 59, 22);
|
||||
assert(SysTime(dt, msecs(213)).fracSecs == msecs(213));
|
||||
assert(SysTime(dt, usecs(5202)).fracSecs == usecs(5202));
|
||||
assert(SysTime(dt, hnsecs(1234567)).fracSecs == hnsecs(1234567));
|
||||
|
||||
// SysTime and Duration both have a precision of hnsecs (100 ns),
|
||||
// so nsecs are going to be truncated.
|
||||
assert(SysTime(dt, nsecs(123456789)).fracSecs == nsecs(123456700));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : Duration, msecs, hnsecs, nsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
auto st = SysTime(DateTime(1982, 4, 1, 20, 59, 22));
|
||||
assert(st.fracSecs == Duration.zero);
|
||||
|
||||
st.fracSecs = msecs(213);
|
||||
assert(st.fracSecs == msecs(213));
|
||||
|
||||
st.fracSecs = hnsecs(1234567);
|
||||
assert(st.fracSecs == hnsecs(1234567));
|
||||
|
||||
// SysTime has a precision of hnsecs (100 ns), so nsecs are
|
||||
// going to be truncated.
|
||||
st.fracSecs = nsecs(123456789);
|
||||
assert(st.fracSecs == hnsecs(1234567));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : hours;
|
||||
import std.datetime.date : DateTime;
|
||||
import std.datetime.timezone : SimpleTimeZone, UTC;
|
||||
|
||||
assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0);
|
||||
|
||||
auto pst = new immutable SimpleTimeZone(hours(-8));
|
||||
assert(SysTime(DateTime(1970, 1, 1), pst).toUnixTime() == 28800);
|
||||
|
||||
auto utc = SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC());
|
||||
assert(utc.toUnixTime() == 1_198_311_285);
|
||||
|
||||
auto ca = SysTime(DateTime(2007, 12, 22, 8, 14, 45), pst);
|
||||
assert(ca.toUnixTime() == 1_198_340_085);
|
||||
|
||||
static void testScope(scope ref SysTime st) @safe
|
||||
{
|
||||
auto result = st.toUnixTime();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : hours;
|
||||
import std.datetime.date : DateTime;
|
||||
import std.datetime.timezone : SimpleTimeZone, UTC;
|
||||
|
||||
assert(SysTime.fromUnixTime(0) ==
|
||||
SysTime(DateTime(1970, 1, 1), UTC()));
|
||||
|
||||
auto pst = new immutable SimpleTimeZone(hours(-8));
|
||||
assert(SysTime.fromUnixTime(28800) ==
|
||||
SysTime(DateTime(1970, 1, 1), pst));
|
||||
|
||||
auto st1 = SysTime.fromUnixTime(1_198_311_285, UTC());
|
||||
assert(st1 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
|
||||
assert(st1.timezone is UTC());
|
||||
assert(st1 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
|
||||
|
||||
auto st2 = SysTime.fromUnixTime(1_198_311_285, pst);
|
||||
assert(st2 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
|
||||
assert(st2.timezone is pst);
|
||||
assert(st2 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.date : AllowDayOverflow, DateTime;
|
||||
|
||||
auto st1 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
|
||||
st1.roll!"months"(1);
|
||||
assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 33, 33)));
|
||||
|
||||
auto st2 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
|
||||
st2.roll!"months"(-1);
|
||||
assert(st2 == SysTime(DateTime(2010, 12, 1, 12, 33, 33)));
|
||||
|
||||
auto st3 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
|
||||
st3.roll!"months"(1);
|
||||
assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 33, 33)));
|
||||
|
||||
auto st4 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
|
||||
st4.roll!"months"(1, AllowDayOverflow.no);
|
||||
assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 33, 33)));
|
||||
|
||||
auto st5 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
|
||||
st5.roll!"years"(1);
|
||||
assert(st5 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
|
||||
|
||||
auto st6 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
|
||||
st6.roll!"years"(1, AllowDayOverflow.no);
|
||||
assert(st6 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : msecs, hnsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
auto st1 = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
|
||||
st1.roll!"days"(1);
|
||||
assert(st1 == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
|
||||
st1.roll!"days"(365);
|
||||
assert(st1 == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
|
||||
st1.roll!"days"(-32);
|
||||
assert(st1 == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
|
||||
|
||||
auto st2 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
|
||||
st2.roll!"hours"(1);
|
||||
assert(st2 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
|
||||
|
||||
auto st3 = SysTime(DateTime(2010, 2, 12, 12, 0, 0));
|
||||
st3.roll!"hours"(-1);
|
||||
assert(st3 == SysTime(DateTime(2010, 2, 12, 11, 0, 0)));
|
||||
|
||||
auto st4 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
|
||||
st4.roll!"minutes"(1);
|
||||
assert(st4 == SysTime(DateTime(2009, 12, 31, 0, 1, 0)));
|
||||
|
||||
auto st5 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
|
||||
st5.roll!"minutes"(-1);
|
||||
assert(st5 == SysTime(DateTime(2010, 1, 1, 0, 59, 0)));
|
||||
|
||||
auto st6 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
|
||||
st6.roll!"seconds"(1);
|
||||
assert(st6 == SysTime(DateTime(2009, 12, 31, 0, 0, 1)));
|
||||
|
||||
auto st7 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
|
||||
st7.roll!"seconds"(-1);
|
||||
assert(st7 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
|
||||
|
||||
auto dt = DateTime(2010, 1, 1, 0, 0, 0);
|
||||
auto st8 = SysTime(dt);
|
||||
st8.roll!"msecs"(1);
|
||||
assert(st8 == SysTime(dt, msecs(1)));
|
||||
|
||||
auto st9 = SysTime(dt);
|
||||
st9.roll!"msecs"(-1);
|
||||
assert(st9 == SysTime(dt, msecs(999)));
|
||||
|
||||
auto st10 = SysTime(dt);
|
||||
st10.roll!"hnsecs"(1);
|
||||
assert(st10 == SysTime(dt, hnsecs(1)));
|
||||
|
||||
auto st11 = SysTime(dt);
|
||||
st11.roll!"hnsecs"(-1);
|
||||
assert(st11 == SysTime(dt, hnsecs(9_999_999)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : hours, seconds;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + seconds(1) ==
|
||||
SysTime(DateTime(2016, 1, 1, 0, 0, 0)));
|
||||
|
||||
assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + hours(1) ==
|
||||
SysTime(DateTime(2016, 1, 1, 0, 59, 59)));
|
||||
|
||||
assert(SysTime(DateTime(2016, 1, 1, 0, 0, 0)) - seconds(1) ==
|
||||
SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
|
||||
|
||||
assert(SysTime(DateTime(2016, 1, 1, 0, 59, 59)) - hours(1) ==
|
||||
SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time;
|
||||
import std.datetime.date : Date;
|
||||
|
||||
assert(SysTime(Date(1999, 2, 1)).diffMonths(
|
||||
SysTime(Date(1999, 1, 31))) == 1);
|
||||
|
||||
assert(SysTime(Date(1999, 1, 31)).diffMonths(
|
||||
SysTime(Date(1999, 2, 1))) == -1);
|
||||
|
||||
assert(SysTime(Date(1999, 3, 1)).diffMonths(
|
||||
SysTime(Date(1999, 1, 1))) == 2);
|
||||
|
||||
assert(SysTime(Date(1999, 1, 1)).diffMonths(
|
||||
SysTime(Date(1999, 3, 31))) == -2);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1);
|
||||
assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365);
|
||||
assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
|
||||
assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365);
|
||||
assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366);
|
||||
|
||||
assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0);
|
||||
assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365);
|
||||
assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366);
|
||||
|
||||
assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120);
|
||||
assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
auto st = SysTime(DateTime(0, 1, 1, 12, 0, 0));
|
||||
st.dayOfGregorianCal = 1;
|
||||
assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0)));
|
||||
|
||||
st.dayOfGregorianCal = 365;
|
||||
assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0)));
|
||||
|
||||
st.dayOfGregorianCal = 366;
|
||||
assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0)));
|
||||
|
||||
st.dayOfGregorianCal = 0;
|
||||
assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0)));
|
||||
|
||||
st.dayOfGregorianCal = -365;
|
||||
assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0)));
|
||||
|
||||
st.dayOfGregorianCal = -366;
|
||||
assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0)));
|
||||
|
||||
st.dayOfGregorianCal = 730_120;
|
||||
assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0)));
|
||||
|
||||
st.dayOfGregorianCal = 734_137;
|
||||
assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time;
|
||||
import std.datetime.date : Date;
|
||||
|
||||
auto st = SysTime(Date(1999, 7, 6));
|
||||
const cst = SysTime(Date(2010, 5, 1));
|
||||
immutable ist = SysTime(Date(2015, 10, 10));
|
||||
|
||||
assert(st.isoWeek == 27);
|
||||
assert(cst.isoWeek == 17);
|
||||
assert(ist.isoWeek == 41);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : msecs, usecs, hnsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth ==
|
||||
SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
|
||||
|
||||
assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0), msecs(24)).endOfMonth ==
|
||||
SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
|
||||
|
||||
assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27), usecs(5203)).endOfMonth ==
|
||||
SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
|
||||
|
||||
assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9), hnsecs(12345)).endOfMonth ==
|
||||
SysTime(DateTime(2000, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).daysInMonth == 31);
|
||||
assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).daysInMonth == 28);
|
||||
assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).daysInMonth == 29);
|
||||
assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).daysInMonth == 30);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD);
|
||||
assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD);
|
||||
assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
|
||||
assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : msecs, hnsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() ==
|
||||
"20100704T070612");
|
||||
|
||||
assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOString() ==
|
||||
"19981225T021500.024");
|
||||
|
||||
assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() ==
|
||||
"00000105T230959");
|
||||
|
||||
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOString() ==
|
||||
"-00040105T000002.052092");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : msecs, hnsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtString() ==
|
||||
"2010-07-04T07:06:12");
|
||||
|
||||
assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOExtString() ==
|
||||
"1998-12-25T02:15:00.024");
|
||||
|
||||
assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtString() ==
|
||||
"0000-01-05T23:09:59");
|
||||
|
||||
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString() ==
|
||||
"-0004-01-05T00:00:02.052092");
|
||||
|
||||
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString(4) ==
|
||||
"-0004-01-05T00:00:02.0520");
|
||||
|
||||
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString(2) ==
|
||||
"-0004-01-05T00:00:02.05");
|
||||
|
||||
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString(7) ==
|
||||
"-0004-01-05T00:00:02.0520920");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : msecs, hnsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() ==
|
||||
"2010-Jul-04 07:06:12");
|
||||
|
||||
assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toSimpleString() ==
|
||||
"1998-Dec-25 02:15:00.024");
|
||||
|
||||
assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() ==
|
||||
"0000-Jan-05 23:09:59");
|
||||
|
||||
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toSimpleString() ==
|
||||
"-0004-Jan-05 00:00:02.052092");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : hours, msecs, usecs, hnsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
import std.datetime.timezone : SimpleTimeZone, UTC;
|
||||
|
||||
assert(SysTime.fromISOString("20100704T070612") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
|
||||
|
||||
assert(SysTime.fromISOString("19981225T021500.007") ==
|
||||
SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
|
||||
|
||||
assert(SysTime.fromISOString("00000105T230959.00002") ==
|
||||
SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
|
||||
|
||||
assert(SysTime.fromISOString("20130207T043937.000050392") ==
|
||||
SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
|
||||
|
||||
assert(SysTime.fromISOString("-00040105T000002") ==
|
||||
SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
|
||||
|
||||
assert(SysTime.fromISOString(" 20100704T070612 ") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
|
||||
|
||||
assert(SysTime.fromISOString("20100704T070612Z") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
|
||||
|
||||
assert(SysTime.fromISOString("20100704T070612-0800") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12),
|
||||
new immutable SimpleTimeZone(hours(-8))));
|
||||
|
||||
assert(SysTime.fromISOString("20100704T070612+0800") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12),
|
||||
new immutable SimpleTimeZone(hours(8))));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : hours, msecs, usecs, hnsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
import std.datetime.timezone : SimpleTimeZone, UTC;
|
||||
|
||||
assert(SysTime.fromISOExtString("2010-07-04T07:06:12") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
|
||||
|
||||
assert(SysTime.fromISOExtString("1998-12-25T02:15:00.007") ==
|
||||
SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
|
||||
|
||||
assert(SysTime.fromISOExtString("0000-01-05T23:09:59.00002") ==
|
||||
SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
|
||||
|
||||
assert(SysTime.fromISOExtString("2013-02-07T04:39:37.000050392") ==
|
||||
SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
|
||||
|
||||
assert(SysTime.fromISOExtString("-0004-01-05T00:00:02") ==
|
||||
SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
|
||||
|
||||
assert(SysTime.fromISOExtString(" 2010-07-04T07:06:12 ") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
|
||||
|
||||
assert(SysTime.fromISOExtString("2010-07-04T07:06:12Z") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
|
||||
|
||||
assert(SysTime.fromISOExtString("2010-07-04T07:06:12-08:00") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12),
|
||||
new immutable SimpleTimeZone(hours(-8))));
|
||||
assert(SysTime.fromISOExtString("2010-07-04T07:06:12+08:00") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12),
|
||||
new immutable SimpleTimeZone(hours(8))));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : hours, msecs, usecs, hnsecs;
|
||||
import std.datetime.date : DateTime;
|
||||
import std.datetime.timezone : SimpleTimeZone, UTC;
|
||||
|
||||
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
|
||||
|
||||
assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") ==
|
||||
SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
|
||||
|
||||
assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") ==
|
||||
SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
|
||||
|
||||
assert(SysTime.fromSimpleString("2013-Feb-07 04:39:37.000050392") ==
|
||||
SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
|
||||
|
||||
assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
|
||||
SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
|
||||
|
||||
assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
|
||||
|
||||
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
|
||||
|
||||
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-08:00") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12),
|
||||
new immutable SimpleTimeZone(hours(-8))));
|
||||
|
||||
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+08:00") ==
|
||||
SysTime(DateTime(2010, 7, 4, 7, 6, 12),
|
||||
new immutable SimpleTimeZone(hours(8))));
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : days, hours, seconds;
|
||||
import std.datetime.date : Date, DateTime;
|
||||
import std.datetime.timezone : SimpleTimeZone, UTC;
|
||||
|
||||
const dt = DateTime(2018, 1, 1, 10, 30, 0);
|
||||
// make a specific point in time in the UTC timezone
|
||||
auto st = SysTime(dt, UTC());
|
||||
assert(st.year == 2018);
|
||||
assert(st.hour == 10);
|
||||
|
||||
// cast to convert
|
||||
assert(cast(DateTime) st == dt);
|
||||
assert(cast(Date) st == Date(2018, 1, 1));
|
||||
|
||||
// make a specific point in time in the New York timezone
|
||||
const ny = SysTime(dt,
|
||||
new immutable SimpleTimeZone(-5.hours, "America/New_York")
|
||||
);
|
||||
assert(ny != st);
|
||||
assert(ny.hour == 10);
|
||||
|
||||
// ISO standard time strings
|
||||
assert(st.toISOString() == "20180101T103000Z");
|
||||
assert(st.toISOExtString() == "2018-01-01T10:30:00Z");
|
||||
|
||||
// add two days and 30 seconds
|
||||
st += 2.days + 30.seconds;
|
||||
assert(st.toISOExtString() == "2018-01-03T10:30:30Z");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.date : DateTime;
|
||||
import std.datetime.timezone : UTC;
|
||||
|
||||
// Midnight, January 1st, 1970
|
||||
assert(unixTimeToStdTime(0) == 621_355_968_000_000_000L);
|
||||
assert(SysTime(unixTimeToStdTime(0)) ==
|
||||
SysTime(DateTime(1970, 1, 1), UTC()));
|
||||
|
||||
assert(unixTimeToStdTime(int.max) == 642_830_804_470_000_000L);
|
||||
assert(SysTime(unixTimeToStdTime(int.max)) ==
|
||||
SysTime(DateTime(2038, 1, 19, 3, 14, 7), UTC()));
|
||||
|
||||
assert(unixTimeToStdTime(-127_127) == 621_354_696_730_000_000L);
|
||||
assert(SysTime(unixTimeToStdTime(-127_127)) ==
|
||||
SysTime(DateTime(1969, 12, 30, 12, 41, 13), UTC()));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
// Midnight, January 1st, 1970 UTC
|
||||
assert(stdTimeToUnixTime(621_355_968_000_000_000L) == 0);
|
||||
|
||||
// 2038-01-19 03:14:07 UTC
|
||||
assert(stdTimeToUnixTime(642_830_804_470_000_000L) == int.max);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(DosFileTimeToSysTime(0b00000000001000010000000000000000) == SysTime(DateTime(1980, 1, 1, 0, 0, 0)));
|
||||
assert(DosFileTimeToSysTime(0b11111111100111111011111101111101) == SysTime(DateTime(2107, 12, 31, 23, 59, 58)));
|
||||
assert(DosFileTimeToSysTime(0x3E3F8456) == SysTime(DateTime(2011, 1, 31, 16, 34, 44)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import std.datetime.date : DateTime;
|
||||
|
||||
assert(SysTimeToDosFileTime(SysTime(DateTime(1980, 1, 1, 0, 0, 0))) == 0b00000000001000010000000000000000);
|
||||
assert(SysTimeToDosFileTime(SysTime(DateTime(2107, 12, 31, 23, 59, 58))) == 0b11111111100111111011111101111101);
|
||||
assert(SysTimeToDosFileTime(SysTime(DateTime(2011, 1, 31, 16, 34, 44))) == 0x3E3F8456);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.datetime.systime;
|
||||
|
||||
import core.time : hours;
|
||||
import std.datetime.date : DateTime, DateTimeException;
|
||||
import std.datetime.timezone : SimpleTimeZone, UTC;
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto tz = new immutable SimpleTimeZone(hours(-8));
|
||||
assert(parseRFC822DateTime("Sat, 6 Jan 1990 12:14:19 -0800") ==
|
||||
SysTime(DateTime(1990, 1, 6, 12, 14, 19), tz));
|
||||
|
||||
assert(parseRFC822DateTime("9 Jul 2002 13:11 +0000") ==
|
||||
SysTime(DateTime(2002, 7, 9, 13, 11, 0), UTC()));
|
||||
|
||||
auto badStr = "29 Feb 2001 12:17:16 +0200";
|
||||
assertThrown!DateTimeException(parseRFC822DateTime(badStr));
|
||||
}
|
||||
|
15
libphobos/testsuite/libphobos.phobos/std_datetime_timezone.d
Normal file
15
libphobos/testsuite/libphobos.phobos/std_datetime_timezone.d
Normal file
|
@ -0,0 +1,15 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.datetime.timezone;
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
auto tz = PosixTimeZone.getTimeZone("America/Los_Angeles");
|
||||
|
||||
assert(tz.name == "America/Los_Angeles");
|
||||
assert(tz.stdName == "PST");
|
||||
assert(tz.dstName == "PDT");
|
||||
}
|
||||
|
||||
}
|
||||
|
33
libphobos/testsuite/libphobos.phobos/std_demangle.d
Normal file
33
libphobos/testsuite/libphobos.phobos/std_demangle.d
Normal file
|
@ -0,0 +1,33 @@
|
|||
@safe pure unittest
|
||||
{
|
||||
import std.demangle;
|
||||
|
||||
// int b in module a
|
||||
assert(demangle("_D1a1bi") == "int a.b");
|
||||
// char array foo in module test
|
||||
assert(demangle("_D4test3fooAa") == "char[] test.foo");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.demangle;
|
||||
|
||||
import std.ascii : isAlphaNum;
|
||||
import std.algorithm.iteration : chunkBy, joiner, map;
|
||||
import std.algorithm.mutation : copy;
|
||||
import std.conv : to;
|
||||
import std.demangle : demangle;
|
||||
import std.functional : pipe;
|
||||
import std.stdio : stdin, stdout;
|
||||
|
||||
void main()
|
||||
{
|
||||
stdin.byLineCopy
|
||||
.map!(
|
||||
l => l.chunkBy!(a => isAlphaNum(a) || a == '_')
|
||||
.map!(a => a[1].pipe!(to!string, demangle)).joiner
|
||||
)
|
||||
.copy(stdout.lockingTextWriter);
|
||||
}
|
||||
}
|
||||
|
207
libphobos/testsuite/libphobos.phobos/std_digest_crc.d
Normal file
207
libphobos/testsuite/libphobos.phobos/std_digest_crc.d
Normal file
|
@ -0,0 +1,207 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
//Template API
|
||||
import std.digest.crc;
|
||||
|
||||
ubyte[4] hash = crc32Of("The quick brown fox jumps over the lazy dog");
|
||||
assert(crcHexString(hash) == "414FA339");
|
||||
|
||||
//Feeding data
|
||||
ubyte[1024] data;
|
||||
CRC32 crc;
|
||||
crc.put(data[]);
|
||||
crc.start(); //Start again
|
||||
crc.put(data[]);
|
||||
hash = crc.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
//OOP API
|
||||
import std.digest.crc;
|
||||
|
||||
auto crc = new CRC32Digest();
|
||||
ubyte[] hash = crc.digest("The quick brown fox jumps over the lazy dog");
|
||||
assert(crcHexString(hash) == "414FA339"); //352441c2
|
||||
|
||||
//Feeding data
|
||||
ubyte[1024] data;
|
||||
crc.put(data[]);
|
||||
crc.reset(); //Start again
|
||||
crc.put(data[]);
|
||||
hash = crc.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
//Simple example, hashing a string using crc32Of helper function
|
||||
ubyte[4] hash32 = crc32Of("abc");
|
||||
//Let's get a hash string
|
||||
assert(crcHexString(hash32) == "352441C2");
|
||||
// Repeat for CRC64
|
||||
ubyte[8] hash64ecma = crc64ECMAOf("abc");
|
||||
assert(crcHexString(hash64ecma) == "2CD8094A1A277627");
|
||||
ubyte[8] hash64iso = crc64ISOOf("abc");
|
||||
assert(crcHexString(hash64iso) == "3776C42000000000");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
ubyte[1024] data;
|
||||
//Using the basic API
|
||||
CRC32 hash32;
|
||||
CRC64ECMA hash64ecma;
|
||||
CRC64ISO hash64iso;
|
||||
//Initialize data here...
|
||||
hash32.put(data);
|
||||
ubyte[4] result32 = hash32.finish();
|
||||
hash64ecma.put(data);
|
||||
ubyte[8] result64ecma = hash64ecma.finish();
|
||||
hash64iso.put(data);
|
||||
ubyte[8] result64iso = hash64iso.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
//Let's use the template features:
|
||||
//Note: When passing a CRC32 to a function, it must be passed by reference!
|
||||
void doSomething(T)(ref T hash)
|
||||
if (isDigest!T)
|
||||
{
|
||||
hash.put(cast(ubyte) 0);
|
||||
}
|
||||
CRC32 crc32;
|
||||
crc32.start();
|
||||
doSomething(crc32);
|
||||
assert(crcHexString(crc32.finish()) == "D202EF8D");
|
||||
// repeat for CRC64
|
||||
CRC64ECMA crc64ecma;
|
||||
crc64ecma.start();
|
||||
doSomething(crc64ecma);
|
||||
assert(crcHexString(crc64ecma.finish()) == "1FADA17364673F59");
|
||||
CRC64ISO crc64iso;
|
||||
crc64iso.start();
|
||||
doSomething(crc64iso);
|
||||
assert(crcHexString(crc64iso.finish()) == "6F90000000000000");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
ubyte[] data = [4,5,7,25];
|
||||
assert(data.crc32Of == [167, 180, 199, 131]);
|
||||
|
||||
import std.utf : byChar;
|
||||
assert("hello"d.byChar.crc32Of == [134, 166, 16, 54]);
|
||||
|
||||
ubyte[4] hash = "abc".crc32Of();
|
||||
assert(hash == digest!CRC32("ab", "c"));
|
||||
|
||||
import std.range : iota;
|
||||
enum ubyte S = 5, F = 66;
|
||||
assert(iota(S, F).crc32Of == [59, 140, 234, 154]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
ubyte[] data = [4,5,7,25];
|
||||
assert(data.crc64ECMAOf == [58, 142, 220, 214, 118, 98, 105, 69]);
|
||||
|
||||
import std.utf : byChar;
|
||||
assert("hello"d.byChar.crc64ECMAOf == [177, 55, 185, 219, 229, 218, 30, 155]);
|
||||
|
||||
ubyte[8] hash = "abc".crc64ECMAOf();
|
||||
assert("abc".crc64ECMAOf == [39, 118, 39, 26, 74, 9, 216, 44]);
|
||||
assert(hash == digest!CRC64ECMA("ab", "c"));
|
||||
|
||||
import std.range : iota;
|
||||
enum ubyte S = 5, F = 66;
|
||||
assert(iota(S, F).crc64ECMAOf == [6, 184, 91, 238, 46, 213, 127, 188]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
ubyte[] data = [4,5,7,25];
|
||||
assert(data.crc64ISOOf == [0, 0, 0, 80, 137, 232, 203, 120]);
|
||||
|
||||
import std.utf : byChar;
|
||||
assert("hello"d.byChar.crc64ISOOf == [0, 0, 16, 216, 226, 238, 62, 60]);
|
||||
|
||||
ubyte[8] hash = "abc".crc64ISOOf();
|
||||
assert("abc".crc64ISOOf == [0, 0, 0, 0, 32, 196, 118, 55]);
|
||||
assert(hash == digest!CRC64ISO("ab", "c"));
|
||||
|
||||
import std.range : iota;
|
||||
enum ubyte S = 5, F = 66;
|
||||
|
||||
assert(iota(S, F).crc64ISOOf == [21, 185, 116, 95, 219, 11, 54, 7]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
//Simple example, hashing a string using CRC32Digest.digest helper function
|
||||
auto crc = new CRC32Digest();
|
||||
ubyte[] hash = crc.digest("abc");
|
||||
//Let's get a hash string
|
||||
assert(crcHexString(hash) == "352441C2");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
//Let's use the OOP features:
|
||||
void test(Digest dig)
|
||||
{
|
||||
dig.put(cast(ubyte) 0);
|
||||
}
|
||||
auto crc = new CRC32Digest();
|
||||
test(crc);
|
||||
|
||||
//Let's use a custom buffer:
|
||||
ubyte[4] buf;
|
||||
ubyte[] result = crc.finish(buf[]);
|
||||
assert(crcHexString(result) == "D202EF8D");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
//Simple example
|
||||
auto hash = new CRC32Digest();
|
||||
hash.put(cast(ubyte) 0);
|
||||
ubyte[] result = hash.finish();
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest.crc;
|
||||
|
||||
//using a supplied buffer
|
||||
ubyte[4] buf;
|
||||
auto hash = new CRC32Digest();
|
||||
hash.put(cast(ubyte) 0);
|
||||
ubyte[] result = hash.finish(buf[]);
|
||||
//The result is now in result (and in buf. If you pass a buffer which is bigger than
|
||||
//necessary, result will have the correct length, but buf will still have it's original
|
||||
//length)
|
||||
}
|
||||
|
145
libphobos/testsuite/libphobos.phobos/std_digest_hmac.d
Normal file
145
libphobos/testsuite/libphobos.phobos/std_digest_hmac.d
Normal file
|
@ -0,0 +1,145 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.digest.hmac;
|
||||
|
||||
import std.ascii : LetterCase;
|
||||
import std.digest : toHexString;
|
||||
import std.digest.sha : SHA1;
|
||||
import std.string : representation;
|
||||
|
||||
auto secret = "secret".representation;
|
||||
assert("The quick brown fox jumps over the lazy dog"
|
||||
.representation
|
||||
.hmac!SHA1(secret)
|
||||
.toHexString!(LetterCase.lower) == "198ea1ea04c435c1246b586a06d5cf11c3ffcda6");
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.digest.hmac;
|
||||
|
||||
import std.digest.sha : SHA1;
|
||||
import std.string : representation;
|
||||
auto hmac = HMAC!SHA1("My s3cR3T keY".representation);
|
||||
hmac.put("Hello, world".representation);
|
||||
static immutable expected = [
|
||||
130, 32, 235, 44, 208, 141,
|
||||
150, 232, 211, 214, 162, 195,
|
||||
188, 127, 52, 89, 100, 68, 90, 216];
|
||||
assert(hmac.finish() == expected);
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.digest.hmac;
|
||||
|
||||
import std.digest.sha : SHA1;
|
||||
import std.string : representation;
|
||||
string data1 = "Hello, world", data2 = "Hola mundo";
|
||||
auto hmac = HMAC!SHA1("My s3cR3T keY".representation);
|
||||
hmac.put(data1.representation);
|
||||
hmac.start(); // reset digest
|
||||
hmac.put(data2.representation); // start over
|
||||
static immutable expected = [
|
||||
122, 151, 232, 240, 249, 80,
|
||||
19, 178, 186, 77, 110, 23, 208,
|
||||
52, 11, 88, 34, 151, 192, 255];
|
||||
assert(hmac.finish() == expected);
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.digest.hmac;
|
||||
|
||||
import std.digest.hmac, std.digest.sha;
|
||||
import std.string : representation;
|
||||
string data1 = "Hello, world", data2 = "Hola mundo";
|
||||
auto hmac = HMAC!SHA1("My s3cR3T keY".representation);
|
||||
hmac.put(data1.representation)
|
||||
.put(data2.representation);
|
||||
static immutable expected = [
|
||||
197, 57, 52, 3, 13, 194, 13,
|
||||
36, 117, 228, 8, 11, 111, 51,
|
||||
165, 3, 123, 31, 251, 113];
|
||||
assert(hmac.finish() == expected);
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.digest.hmac;
|
||||
|
||||
import std.digest.sha : SHA1;
|
||||
import std.string : representation;
|
||||
string data1 = "Hello, world", data2 = "Hola mundo";
|
||||
auto hmac = HMAC!SHA1("My s3cR3T keY".representation);
|
||||
auto testDigest = hmac.put(data1.representation)
|
||||
.put(data2.representation)
|
||||
.finish();
|
||||
static immutable expected = [
|
||||
197, 57, 52, 3, 13, 194, 13,
|
||||
36, 117, 228, 8, 11, 111, 51,
|
||||
165, 3, 123, 31, 251, 113];
|
||||
assert(testDigest == expected);
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.digest.hmac;
|
||||
|
||||
import std.digest.sha : SHA1;
|
||||
import std.string : representation;
|
||||
string data1 = "Hello, world", data2 = "Hola mundo";
|
||||
auto digest = hmac!SHA1("My s3cR3T keY".representation)
|
||||
.put(data1.representation)
|
||||
.put(data2.representation)
|
||||
.finish();
|
||||
static immutable expected = [
|
||||
197, 57, 52, 3, 13, 194, 13, 36,
|
||||
117, 228, 8, 11, 111, 51, 165,
|
||||
3, 123, 31, 251, 113];
|
||||
assert(digest == expected);
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.digest.hmac;
|
||||
|
||||
import std.algorithm.iteration : map;
|
||||
import std.digest.sha : SHA1;
|
||||
import std.string : representation;
|
||||
string data = "Hello, world";
|
||||
auto digest = data.representation
|
||||
.map!(a => cast(ubyte)(a+1))
|
||||
.hmac!SHA1("My s3cR3T keY".representation);
|
||||
static assert(is(typeof(digest) == ubyte[20]));
|
||||
static immutable expected = [
|
||||
163, 208, 118, 179, 216, 93,
|
||||
17, 10, 84, 200, 87, 104, 244,
|
||||
111, 136, 214, 167, 210, 58, 10];
|
||||
assert(digest == expected);
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.digest.hmac;
|
||||
|
||||
import std.digest.sha : SHA1;
|
||||
import std.string : representation;
|
||||
string data1 = "Hello, world", data2 = "Hola mundo";
|
||||
auto hmac = HMAC!SHA1("My s3cR3T keY".representation);
|
||||
auto digest = hmac.put(data1.representation)
|
||||
.put(data2.representation)
|
||||
.finish();
|
||||
static immutable expected = [
|
||||
197, 57, 52, 3, 13, 194, 13,
|
||||
36, 117, 228, 8, 11, 111, 51,
|
||||
165, 3, 123, 31, 251, 113];
|
||||
assert(digest == expected);
|
||||
}
|
||||
|
124
libphobos/testsuite/libphobos.phobos/std_digest_md.d
Normal file
124
libphobos/testsuite/libphobos.phobos/std_digest_md.d
Normal file
|
@ -0,0 +1,124 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.digest.md;
|
||||
|
||||
//Template API
|
||||
import std.digest.md;
|
||||
|
||||
//Feeding data
|
||||
ubyte[1024] data;
|
||||
MD5 md5;
|
||||
md5.start();
|
||||
md5.put(data[]);
|
||||
md5.start(); //Start again
|
||||
md5.put(data[]);
|
||||
auto hash = md5.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.md;
|
||||
|
||||
//OOP API
|
||||
import std.digest.md;
|
||||
|
||||
auto md5 = new MD5Digest();
|
||||
ubyte[] hash = md5.digest("abc");
|
||||
assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72");
|
||||
|
||||
//Feeding data
|
||||
ubyte[1024] data;
|
||||
md5.put(data[]);
|
||||
md5.reset(); //Start again
|
||||
md5.put(data[]);
|
||||
hash = md5.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.md;
|
||||
|
||||
//Simple example
|
||||
MD5 hash;
|
||||
hash.start();
|
||||
hash.put(cast(ubyte) 0);
|
||||
ubyte[16] result = hash.finish();
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.md;
|
||||
|
||||
//Simple example, hashing a string using md5Of helper function
|
||||
ubyte[16] hash = md5Of("abc");
|
||||
//Let's get a hash string
|
||||
assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.md;
|
||||
|
||||
//Using the basic API
|
||||
MD5 hash;
|
||||
hash.start();
|
||||
ubyte[1024] data;
|
||||
//Initialize data here...
|
||||
hash.put(data);
|
||||
ubyte[16] result = hash.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.md;
|
||||
|
||||
//Let's use the template features:
|
||||
void doSomething(T)(ref T hash)
|
||||
if (isDigest!T)
|
||||
{
|
||||
hash.put(cast(ubyte) 0);
|
||||
}
|
||||
MD5 md5;
|
||||
md5.start();
|
||||
doSomething(md5);
|
||||
assert(toHexString(md5.finish()) == "93B885ADFE0DA089CDF634904FD59F71");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.md;
|
||||
|
||||
ubyte[16] hash = md5Of("abc");
|
||||
assert(hash == digest!MD5("abc"));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.md;
|
||||
|
||||
//Simple example, hashing a string using Digest.digest helper function
|
||||
auto md5 = new MD5Digest();
|
||||
ubyte[] hash = md5.digest("abc");
|
||||
//Let's get a hash string
|
||||
assert(toHexString(hash) == "900150983CD24FB0D6963F7D28E17F72");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest.md;
|
||||
|
||||
//Let's use the OOP features:
|
||||
void test(Digest dig)
|
||||
{
|
||||
dig.put(cast(ubyte) 0);
|
||||
}
|
||||
auto md5 = new MD5Digest();
|
||||
test(md5);
|
||||
|
||||
//Let's use a custom buffer:
|
||||
ubyte[16] buf;
|
||||
ubyte[] result = md5.finish(buf[]);
|
||||
assert(toHexString(result) == "93B885ADFE0DA089CDF634904FD59F71");
|
||||
}
|
||||
|
82
libphobos/testsuite/libphobos.phobos/std_digest_murmurhash.d
Normal file
82
libphobos/testsuite/libphobos.phobos/std_digest_murmurhash.d
Normal file
|
@ -0,0 +1,82 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.digest.murmurhash;
|
||||
|
||||
// MurmurHash3!32, MurmurHash3!(128, 32) and MurmurHash3!(128, 64) implement
|
||||
// the std.digest Template API.
|
||||
static assert(isDigest!(MurmurHash3!32));
|
||||
// The convenient digest template allows for quick hashing of any data.
|
||||
ubyte[4] hashed = digest!(MurmurHash3!32)([1, 2, 3, 4]);
|
||||
assert(hashed == [0, 173, 69, 68]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.murmurhash;
|
||||
|
||||
// One can also hash ubyte data piecewise by instanciating a hasher and call
|
||||
// the 'put' method.
|
||||
const(ubyte)[] data1 = [1, 2, 3];
|
||||
const(ubyte)[] data2 = [4, 5, 6, 7];
|
||||
// The incoming data will be buffered and hashed element by element.
|
||||
MurmurHash3!32 hasher;
|
||||
hasher.put(data1);
|
||||
hasher.put(data2);
|
||||
// The call to 'finish' ensures:
|
||||
// - the remaining bits are processed
|
||||
// - the hash gets finalized
|
||||
auto hashed = hasher.finish();
|
||||
assert(hashed == [181, 151, 88, 252]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.murmurhash;
|
||||
|
||||
// Using `putElements`, `putRemainder` and `finalize` you gain full
|
||||
// control over which part of the algorithm to run.
|
||||
// This allows for maximum throughput but needs extra care.
|
||||
|
||||
// Data type must be the same as the hasher's element type:
|
||||
// - uint for MurmurHash3!32
|
||||
// - uint[4] for MurmurHash3!(128, 32)
|
||||
// - ulong[2] for MurmurHash3!(128, 64)
|
||||
const(uint)[] data = [1, 2, 3, 4];
|
||||
// Note the hasher starts with 'Fast'.
|
||||
MurmurHash3!32 hasher;
|
||||
// Push as many array of elements as you need. The less calls the better.
|
||||
hasher.putElements(data);
|
||||
// Put remainder bytes if needed. This method can be called only once.
|
||||
hasher.putRemainder(ubyte(1), ubyte(1), ubyte(1));
|
||||
// Call finalize to incorporate data length in the hash.
|
||||
hasher.finalize();
|
||||
// Finally get the hashed value.
|
||||
auto hashed = hasher.getBytes();
|
||||
assert(hashed == [188, 165, 108, 2]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.murmurhash;
|
||||
|
||||
ubyte[4] hashed = digest!(MurmurHash3!32)([1, 2, 3, 4]);
|
||||
assert(hashed == [0, 173, 69, 68]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.murmurhash;
|
||||
|
||||
const(ubyte)[] data1 = [1, 2, 3];
|
||||
const(ubyte)[] data2 = [4, 5, 6, 7];
|
||||
// The incoming data will be buffered and hashed element by element.
|
||||
MurmurHash3!32 hasher;
|
||||
hasher.put(data1);
|
||||
hasher.put(data2);
|
||||
// The call to 'finish' ensures:
|
||||
// - the remaining bits are processed
|
||||
// - the hash gets finalized
|
||||
auto hashed = hasher.finish();
|
||||
assert(hashed == [181, 151, 88, 252]);
|
||||
}
|
||||
|
492
libphobos/testsuite/libphobos.phobos/std_digest_package.d
Normal file
492
libphobos/testsuite/libphobos.phobos/std_digest_package.d
Normal file
|
@ -0,0 +1,492 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
|
||||
//Simple example
|
||||
char[8] hexHash = hexDigest!CRC32("The quick brown fox jumps over the lazy dog");
|
||||
assert(hexHash == "39A34F41");
|
||||
|
||||
//Simple example, using the API manually
|
||||
CRC32 context = makeDigest!CRC32();
|
||||
context.put(cast(ubyte[])"The quick brown fox jumps over the lazy dog");
|
||||
ubyte[4] hash = context.finish();
|
||||
assert(toHexString(hash) == "39A34F41");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
//Generating the hashes of a file, idiomatic D way
|
||||
import std.digest.crc, std.digest.md, std.digest.sha;
|
||||
import std.stdio;
|
||||
|
||||
// Digests a file and prints the result.
|
||||
void digestFile(Hash)(string filename)
|
||||
if (isDigest!Hash)
|
||||
{
|
||||
auto file = File(filename);
|
||||
auto result = digest!Hash(file.byChunk(4096 * 1024));
|
||||
writefln("%s (%s) = %s", Hash.stringof, filename, toHexString(result));
|
||||
}
|
||||
|
||||
void main(string[] args)
|
||||
{
|
||||
foreach (name; args[1 .. $])
|
||||
{
|
||||
digestFile!MD5(name);
|
||||
digestFile!SHA1(name);
|
||||
digestFile!CRC32(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
//Generating the hashes of a file using the template API
|
||||
import std.digest.crc, std.digest.md, std.digest.sha;
|
||||
import std.stdio;
|
||||
// Digests a file and prints the result.
|
||||
void digestFile(Hash)(ref Hash hash, string filename)
|
||||
if (isDigest!Hash)
|
||||
{
|
||||
File file = File(filename);
|
||||
|
||||
//As digests imlement OutputRange, we could use std.algorithm.copy
|
||||
//Let's do it manually for now
|
||||
foreach (buffer; file.byChunk(4096 * 1024))
|
||||
hash.put(buffer);
|
||||
|
||||
auto result = hash.finish();
|
||||
writefln("%s (%s) = %s", Hash.stringof, filename, toHexString(result));
|
||||
}
|
||||
|
||||
void uMain(string[] args)
|
||||
{
|
||||
MD5 md5;
|
||||
SHA1 sha1;
|
||||
CRC32 crc32;
|
||||
|
||||
md5.start();
|
||||
sha1.start();
|
||||
crc32.start();
|
||||
|
||||
foreach (arg; args[1 .. $])
|
||||
{
|
||||
digestFile(md5, arg);
|
||||
digestFile(sha1, arg);
|
||||
digestFile(crc32, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc, std.digest.md, std.digest.sha;
|
||||
import std.stdio;
|
||||
|
||||
// Digests a file and prints the result.
|
||||
void digestFile(Digest hash, string filename)
|
||||
{
|
||||
File file = File(filename);
|
||||
|
||||
//As digests implement OutputRange, we could use std.algorithm.copy
|
||||
//Let's do it manually for now
|
||||
foreach (buffer; file.byChunk(4096 * 1024))
|
||||
hash.put(buffer);
|
||||
|
||||
ubyte[] result = hash.finish();
|
||||
writefln("%s (%s) = %s", typeid(hash).toString(), filename, toHexString(result));
|
||||
}
|
||||
|
||||
void umain(string[] args)
|
||||
{
|
||||
auto md5 = new MD5Digest();
|
||||
auto sha1 = new SHA1Digest();
|
||||
auto crc32 = new CRC32Digest();
|
||||
|
||||
foreach (arg; args[1 .. $])
|
||||
{
|
||||
digestFile(md5, arg);
|
||||
digestFile(sha1, arg);
|
||||
digestFile(crc32, arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
//Using the OutputRange feature
|
||||
import std.algorithm.mutation : copy;
|
||||
import std.digest.md;
|
||||
import std.range : repeat;
|
||||
|
||||
auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
|
||||
auto ctx = makeDigest!MD5();
|
||||
copy(oneMillionRange, &ctx); //Note: You must pass a pointer to copy!
|
||||
assert(ctx.finish().toHexString() == "7707D6AE4E027C70EEA2A935C2296F21");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
static assert(isDigest!CRC32);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
void myFunction(T)()
|
||||
if (isDigest!T)
|
||||
{
|
||||
T dig;
|
||||
dig.start();
|
||||
auto result = dig.finish();
|
||||
}
|
||||
myFunction!CRC32();
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
assert(is(DigestType!(CRC32) == ubyte[4]));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
CRC32 dig;
|
||||
dig.start();
|
||||
DigestType!CRC32 result = dig.finish();
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc, std.digest.md;
|
||||
assert(!hasPeek!(MD5));
|
||||
assert(hasPeek!CRC32);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
void myFunction(T)()
|
||||
if (hasPeek!T)
|
||||
{
|
||||
T dig;
|
||||
dig.start();
|
||||
auto result = dig.peek();
|
||||
}
|
||||
myFunction!CRC32();
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.hmac, std.digest.md;
|
||||
static assert(hasBlockSize!MD5 && MD5.blockSize == 512);
|
||||
static assert(hasBlockSize!(HMAC!MD5) && HMAC!MD5.blockSize == 512);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.md;
|
||||
import std.range : repeat;
|
||||
auto testRange = repeat!ubyte(cast(ubyte)'a', 100);
|
||||
auto md5 = digest!MD5(testRange);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc, std.digest.md, std.digest.sha;
|
||||
auto md5 = digest!MD5( "The quick brown fox jumps over the lazy dog");
|
||||
auto sha1 = digest!SHA1( "The quick brown fox jumps over the lazy dog");
|
||||
auto crc32 = digest!CRC32("The quick brown fox jumps over the lazy dog");
|
||||
assert(toHexString(crc32) == "39A34F41");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog");
|
||||
assert(toHexString(crc32) == "39A34F41");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.md;
|
||||
import std.range : repeat;
|
||||
auto testRange = repeat!ubyte(cast(ubyte)'a', 100);
|
||||
assert(hexDigest!MD5(testRange) == "36A92CC94A9E0FA21F625F8BFB007ADF");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
assert(hexDigest!(CRC32, Order.decreasing)("The quick brown fox jumps over the lazy dog") == "414FA339");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
assert(hexDigest!(CRC32, Order.decreasing)("The quick ", "brown ", "fox jumps over the lazy dog") == "414FA339");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.md;
|
||||
auto md5 = makeDigest!MD5();
|
||||
md5.put(0);
|
||||
assert(toHexString(md5.finish()) == "93B885ADFE0DA089CDF634904FD59F71");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
//Using the OutputRange feature
|
||||
import std.algorithm.mutation : copy;
|
||||
import std.digest.md;
|
||||
import std.range : repeat;
|
||||
|
||||
auto oneMillionRange = repeat!ubyte(cast(ubyte)'a', 1000000);
|
||||
auto ctx = new MD5Digest();
|
||||
copy(oneMillionRange, ctx);
|
||||
assert(ctx.finish().toHexString() == "7707D6AE4E027C70EEA2A935C2296F21");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc, std.digest.md, std.digest.sha;
|
||||
ubyte[] md5 = (new MD5Digest()).digest("The quick brown fox jumps over the lazy dog");
|
||||
ubyte[] sha1 = (new SHA1Digest()).digest("The quick brown fox jumps over the lazy dog");
|
||||
ubyte[] crc32 = (new CRC32Digest()).digest("The quick brown fox jumps over the lazy dog");
|
||||
assert(crcHexString(crc32) == "414FA339");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
ubyte[] crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog");
|
||||
assert(crcHexString(crc32) == "414FA339");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
void test(Digest dig)
|
||||
{
|
||||
dig.put(cast(ubyte) 0); //single ubyte
|
||||
dig.put(cast(ubyte) 0, cast(ubyte) 0); //variadic
|
||||
ubyte[10] buf;
|
||||
dig.put(buf); //buffer
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc : CRC32;
|
||||
|
||||
auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog");
|
||||
assert(crc32.toHexString!(Order.decreasing) == "414FA339");
|
||||
assert(crc32.toHexString!(LetterCase.lower, Order.decreasing) == "414fa339");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
//Test with template API:
|
||||
auto crc32 = digest!CRC32("The quick ", "brown ", "fox jumps over the lazy dog");
|
||||
//Lower case variant:
|
||||
assert(toHexString!(LetterCase.lower)(crc32) == "39a34f41");
|
||||
//Usually CRCs are printed in this order, though:
|
||||
assert(toHexString!(Order.decreasing)(crc32) == "414FA339");
|
||||
assert(toHexString!(LetterCase.lower, Order.decreasing)(crc32) == "414fa339");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.crc;
|
||||
// With OOP API
|
||||
auto crc32 = (new CRC32Digest()).digest("The quick ", "brown ", "fox jumps over the lazy dog");
|
||||
//Usually CRCs are printed in this order, though:
|
||||
assert(toHexString!(Order.decreasing)(crc32) == "414FA339");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.md;
|
||||
//Simple example
|
||||
auto hash = new WrapperDigest!MD5();
|
||||
hash.put(cast(ubyte) 0);
|
||||
auto result = hash.finish();
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
//using a supplied buffer
|
||||
import std.digest.md;
|
||||
ubyte[16] buf;
|
||||
auto hash = new WrapperDigest!MD5();
|
||||
hash.put(cast(ubyte) 0);
|
||||
auto result = hash.finish(buf[]);
|
||||
//The result is now in result (and in buf). If you pass a buffer which is bigger than
|
||||
//necessary, result will have the correct length, but buf will still have it's original
|
||||
//length
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.digest.hmac : hmac;
|
||||
import std.digest.sha : SHA1;
|
||||
import std.string : representation;
|
||||
|
||||
// a typical HMAC data integrity verification
|
||||
auto secret = "A7GZIP6TAQA6OHM7KZ42KB9303CEY0MOV5DD6NTV".representation;
|
||||
auto data = "data".representation;
|
||||
|
||||
auto hex1 = data.hmac!SHA1(secret).toHexString;
|
||||
auto hex2 = data.hmac!SHA1(secret).toHexString;
|
||||
auto hex3 = "data1".representation.hmac!SHA1(secret).toHexString;
|
||||
|
||||
assert( secureEqual(hex1[], hex2[]));
|
||||
assert(!secureEqual(hex1[], hex3[]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
assert(isHexString("0x0123456789ABCDEFabcdef"));
|
||||
assert(isHexString("0123456789ABCDEFabcdef"));
|
||||
assert(!isHexString("g"));
|
||||
assert(!isHexString("#"));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
import std.range.primitives : ElementType, isForwardRange;
|
||||
import std.traits : ReturnType;
|
||||
|
||||
// The decoder implements a forward range.
|
||||
static assert(isForwardRange!(ReturnType!(fromHexStringAsRange!string)));
|
||||
static assert(isForwardRange!(ReturnType!(fromHexStringAsRange!wstring)));
|
||||
static assert(isForwardRange!(ReturnType!(fromHexStringAsRange!dstring)));
|
||||
|
||||
// The element type of the range is always `ubyte`.
|
||||
static assert(
|
||||
is(ElementType!(ReturnType!(fromHexStringAsRange!string)) == ubyte)
|
||||
);
|
||||
static assert(
|
||||
is(ElementType!(ReturnType!(fromHexStringAsRange!wstring)) == ubyte)
|
||||
);
|
||||
static assert(
|
||||
is(ElementType!(ReturnType!(fromHexStringAsRange!dstring)) == ubyte)
|
||||
);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
// Single byte
|
||||
assert("0xff".fromHexString == [255]);
|
||||
assert("0xff"w.fromHexString == [255]);
|
||||
assert("0xff"d.fromHexString == [255]);
|
||||
assert("0xC0".fromHexString == [192]);
|
||||
assert("0x00".fromHexString == [0]);
|
||||
|
||||
// Nothing
|
||||
assert("".fromHexString == []);
|
||||
assert(""w.fromHexString == []);
|
||||
assert(""d.fromHexString == []);
|
||||
|
||||
// Nothing but a prefix
|
||||
assert("0x".fromHexString == []);
|
||||
assert("0x"w.fromHexString == []);
|
||||
assert("0x"d.fromHexString == []);
|
||||
|
||||
// Half a byte
|
||||
assert("0x1".fromHexString == [0x01]);
|
||||
assert("0x1"w.fromHexString == [0x01]);
|
||||
assert("0x1"d.fromHexString == [0x01]);
|
||||
|
||||
// Mixed case is fine.
|
||||
assert("0xAf".fromHexString == [0xAF]);
|
||||
assert("0xaF".fromHexString == [0xAF]);
|
||||
|
||||
// Multiple bytes
|
||||
assert("0xfff".fromHexString == [0x0F, 0xFF]);
|
||||
assert("0x123AaAa".fromHexString == [0x01, 0x23, 0xAA, 0xAA]);
|
||||
assert("EBBBBF".fromHexString == [0xEB, 0xBB, 0xBF]);
|
||||
|
||||
// md5 sum
|
||||
assert("d41d8cd98f00b204e9800998ecf8427e".fromHexString == [
|
||||
0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04,
|
||||
0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E,
|
||||
]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest;
|
||||
|
||||
// Cycle self-test
|
||||
const ubyte[] initial = [0x00, 0x12, 0x34, 0xEB];
|
||||
assert(initial == initial.toHexString().fromHexString());
|
||||
}
|
||||
|
127
libphobos/testsuite/libphobos.phobos/std_digest_ripemd.d
Normal file
127
libphobos/testsuite/libphobos.phobos/std_digest_ripemd.d
Normal file
|
@ -0,0 +1,127 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.digest.ripemd;
|
||||
|
||||
//Template API
|
||||
import std.digest.md;
|
||||
|
||||
ubyte[20] hash = ripemd160Of("abc");
|
||||
assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC");
|
||||
|
||||
//Feeding data
|
||||
ubyte[1024] data;
|
||||
RIPEMD160 md;
|
||||
md.start();
|
||||
md.put(data[]);
|
||||
md.start(); //Start again
|
||||
md.put(data[]);
|
||||
hash = md.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.ripemd;
|
||||
|
||||
//OOP API
|
||||
import std.digest.md;
|
||||
|
||||
auto md = new RIPEMD160Digest();
|
||||
ubyte[] hash = md.digest("abc");
|
||||
assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC");
|
||||
|
||||
//Feeding data
|
||||
ubyte[1024] data;
|
||||
md.put(data[]);
|
||||
md.reset(); //Start again
|
||||
md.put(data[]);
|
||||
hash = md.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.ripemd;
|
||||
|
||||
//Simple example, hashing a string using ripemd160Of helper function
|
||||
ubyte[20] hash = ripemd160Of("abc");
|
||||
//Let's get a hash string
|
||||
assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.ripemd;
|
||||
|
||||
//Using the basic API
|
||||
RIPEMD160 hash;
|
||||
hash.start();
|
||||
ubyte[1024] data;
|
||||
//Initialize data here...
|
||||
hash.put(data);
|
||||
ubyte[20] result = hash.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.ripemd;
|
||||
|
||||
//Let's use the template features:
|
||||
void doSomething(T)(ref T hash)
|
||||
if (isDigest!T)
|
||||
{
|
||||
hash.put(cast(ubyte) 0);
|
||||
}
|
||||
RIPEMD160 md;
|
||||
md.start();
|
||||
doSomething(md);
|
||||
assert(toHexString(md.finish()) == "C81B94933420221A7AC004A90242D8B1D3E5070D");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.ripemd;
|
||||
|
||||
//Simple example
|
||||
RIPEMD160 hash;
|
||||
hash.start();
|
||||
hash.put(cast(ubyte) 0);
|
||||
ubyte[20] result = hash.finish();
|
||||
assert(toHexString(result) == "C81B94933420221A7AC004A90242D8B1D3E5070D");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.ripemd;
|
||||
|
||||
ubyte[20] hash = ripemd160Of("abc");
|
||||
assert(hash == digest!RIPEMD160("abc"));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.ripemd;
|
||||
|
||||
//Simple example, hashing a string using Digest.digest helper function
|
||||
auto md = new RIPEMD160Digest();
|
||||
ubyte[] hash = md.digest("abc");
|
||||
//Let's get a hash string
|
||||
assert(toHexString(hash) == "8EB208F7E05D987A9B044A8E98C6B087F15A0BFC");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest.ripemd;
|
||||
|
||||
//Let's use the OOP features:
|
||||
void test(Digest dig)
|
||||
{
|
||||
dig.put(cast(ubyte) 0);
|
||||
}
|
||||
auto md = new RIPEMD160Digest();
|
||||
test(md);
|
||||
|
||||
//Let's use a custom buffer:
|
||||
ubyte[20] buf;
|
||||
ubyte[] result = md.finish(buf[]);
|
||||
assert(toHexString(result) == "C81B94933420221A7AC004A90242D8B1D3E5070D");
|
||||
}
|
||||
|
163
libphobos/testsuite/libphobos.phobos/std_digest_sha.d
Normal file
163
libphobos/testsuite/libphobos.phobos/std_digest_sha.d
Normal file
|
@ -0,0 +1,163 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.digest.sha;
|
||||
|
||||
//Template API
|
||||
import std.digest.sha;
|
||||
|
||||
ubyte[20] hash1 = sha1Of("abc");
|
||||
assert(toHexString(hash1) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
|
||||
|
||||
ubyte[28] hash224 = sha224Of("abc");
|
||||
assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
|
||||
|
||||
//Feeding data
|
||||
ubyte[1024] data;
|
||||
SHA1 sha1;
|
||||
sha1.start();
|
||||
sha1.put(data[]);
|
||||
sha1.start(); //Start again
|
||||
sha1.put(data[]);
|
||||
hash1 = sha1.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.sha;
|
||||
|
||||
//OOP API
|
||||
import std.digest.sha;
|
||||
|
||||
auto sha1 = new SHA1Digest();
|
||||
ubyte[] hash1 = sha1.digest("abc");
|
||||
assert(toHexString(hash1) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
|
||||
|
||||
auto sha224 = new SHA224Digest();
|
||||
ubyte[] hash224 = sha224.digest("abc");
|
||||
assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
|
||||
|
||||
//Feeding data
|
||||
ubyte[1024] data;
|
||||
sha1.put(data[]);
|
||||
sha1.reset(); //Start again
|
||||
sha1.put(data[]);
|
||||
hash1 = sha1.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.sha;
|
||||
|
||||
//Simple example
|
||||
SHA1 hash;
|
||||
hash.start();
|
||||
hash.put(cast(ubyte) 0);
|
||||
ubyte[20] result = hash.finish();
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.sha;
|
||||
|
||||
//Simple example, hashing a string using sha1Of helper function
|
||||
ubyte[20] hash = sha1Of("abc");
|
||||
//Let's get a hash string
|
||||
assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
|
||||
|
||||
//The same, but using SHA-224
|
||||
ubyte[28] hash224 = sha224Of("abc");
|
||||
assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.sha;
|
||||
|
||||
//Using the basic API
|
||||
SHA1 hash;
|
||||
hash.start();
|
||||
ubyte[1024] data;
|
||||
//Initialize data here...
|
||||
hash.put(data);
|
||||
ubyte[20] result = hash.finish();
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.sha;
|
||||
|
||||
//Let's use the template features:
|
||||
//Note: When passing a SHA1 to a function, it must be passed by reference!
|
||||
void doSomething(T)(ref T hash)
|
||||
if (isDigest!T)
|
||||
{
|
||||
hash.put(cast(ubyte) 0);
|
||||
}
|
||||
SHA1 sha;
|
||||
sha.start();
|
||||
doSomething(sha);
|
||||
assert(toHexString(sha.finish()) == "5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.sha;
|
||||
|
||||
ubyte[20] hash = sha1Of("abc");
|
||||
assert(hash == digest!SHA1("abc"));
|
||||
|
||||
ubyte[28] hash224 = sha224Of("abc");
|
||||
assert(hash224 == digest!SHA224("abc"));
|
||||
|
||||
ubyte[32] hash256 = sha256Of("abc");
|
||||
assert(hash256 == digest!SHA256("abc"));
|
||||
|
||||
ubyte[48] hash384 = sha384Of("abc");
|
||||
assert(hash384 == digest!SHA384("abc"));
|
||||
|
||||
ubyte[64] hash512 = sha512Of("abc");
|
||||
assert(hash512 == digest!SHA512("abc"));
|
||||
|
||||
ubyte[28] hash512_224 = sha512_224Of("abc");
|
||||
assert(hash512_224 == digest!SHA512_224("abc"));
|
||||
|
||||
ubyte[32] hash512_256 = sha512_256Of("abc");
|
||||
assert(hash512_256 == digest!SHA512_256("abc"));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.digest.sha;
|
||||
|
||||
//Simple example, hashing a string using Digest.digest helper function
|
||||
auto sha = new SHA1Digest();
|
||||
ubyte[] hash = sha.digest("abc");
|
||||
//Let's get a hash string
|
||||
assert(toHexString(hash) == "A9993E364706816ABA3E25717850C26C9CD0D89D");
|
||||
|
||||
//The same, but using SHA-224
|
||||
auto sha224 = new SHA224Digest();
|
||||
ubyte[] hash224 = sha224.digest("abc");
|
||||
//Let's get a hash string
|
||||
assert(toHexString(hash224) == "23097D223405D8228642A477BDA255B32AADBCE4BDA0B3F7E36C9DA7");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.digest.sha;
|
||||
|
||||
//Let's use the OOP features:
|
||||
void test(Digest dig)
|
||||
{
|
||||
dig.put(cast(ubyte) 0);
|
||||
}
|
||||
auto sha = new SHA1Digest();
|
||||
test(sha);
|
||||
|
||||
//Let's use a custom buffer:
|
||||
ubyte[20] buf;
|
||||
ubyte[] result = sha.finish(buf[]);
|
||||
assert(toHexString(result) == "5BA93C9DB0CFF93F52B521D7420E43F6EDA2784F");
|
||||
}
|
||||
|
167
libphobos/testsuite/libphobos.phobos/std_encoding.d
Normal file
167
libphobos/testsuite/libphobos.phobos/std_encoding.d
Normal file
|
@ -0,0 +1,167 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
assert(encodingName!(char) == "UTF-8");
|
||||
assert(encodingName!(wchar) == "UTF-16");
|
||||
assert(encodingName!(dchar) == "UTF-32");
|
||||
assert(encodingName!(AsciiChar) == "ASCII");
|
||||
assert(encodingName!(Latin1Char) == "ISO-8859-1");
|
||||
assert(encodingName!(Latin2Char) == "ISO-8859-2");
|
||||
assert(encodingName!(Windows1250Char) == "windows-1250");
|
||||
assert(encodingName!(Windows1251Char) == "windows-1251");
|
||||
assert(encodingName!(Windows1252Char) == "windows-1252");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
assert( canEncode!(Latin1Char)('A'));
|
||||
assert( canEncode!(Latin2Char)('A'));
|
||||
assert(!canEncode!(AsciiChar)('\u00A0'));
|
||||
assert( canEncode!(Latin1Char)('\u00A0'));
|
||||
assert( canEncode!(Latin2Char)('\u00A0'));
|
||||
assert( canEncode!(Windows1250Char)('\u20AC'));
|
||||
assert(!canEncode!(Windows1250Char)('\u20AD'));
|
||||
assert(!canEncode!(Windows1250Char)('\uFFFD'));
|
||||
assert( canEncode!(Windows1251Char)('\u0402'));
|
||||
assert(!canEncode!(Windows1251Char)('\u20AD'));
|
||||
assert(!canEncode!(Windows1251Char)('\uFFFD'));
|
||||
assert( canEncode!(Windows1252Char)('\u20AC'));
|
||||
assert(!canEncode!(Windows1252Char)('\u20AD'));
|
||||
assert(!canEncode!(Windows1252Char)('\uFFFD'));
|
||||
assert(!canEncode!(char)(cast(dchar) 0x110000));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
import std.algorithm.searching : find;
|
||||
import std.utf : byDchar;
|
||||
|
||||
assert("The quick brown fox"
|
||||
.byDchar
|
||||
.find!(x => !canEncode!AsciiChar(x))
|
||||
.empty);
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
assert(!isValidCodeUnit(cast(char) 0xC0));
|
||||
assert(!isValidCodeUnit(cast(char) 0xFF));
|
||||
assert( isValidCodeUnit(cast(wchar) 0xD800));
|
||||
assert(!isValidCodeUnit(cast(dchar) 0xD800));
|
||||
assert(!isValidCodeUnit(cast(AsciiChar) 0xA0));
|
||||
assert( isValidCodeUnit(cast(Windows1250Char) 0x80));
|
||||
assert(!isValidCodeUnit(cast(Windows1250Char) 0x81));
|
||||
assert( isValidCodeUnit(cast(Windows1251Char) 0x80));
|
||||
assert(!isValidCodeUnit(cast(Windows1251Char) 0x98));
|
||||
assert( isValidCodeUnit(cast(Windows1252Char) 0x80));
|
||||
assert(!isValidCodeUnit(cast(Windows1252Char) 0x81));
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
assert( isValid("\u20AC100"));
|
||||
assert(!isValid(cast(char[3])[167, 133, 175]));
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
assert(sanitize("hello \xF0\x80world") == "hello \xEF\xBF\xBDworld");
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
assert(firstSequence("\u20AC1000") == "\u20AC".length);
|
||||
assert(firstSequence("hel") == "h".length);
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
assert(lastSequence("1000\u20AC") == "\u20AC".length);
|
||||
assert(lastSequence("hellö") == "ö".length);
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
assert(index("\u20AC100",1) == 3);
|
||||
assert(index("hällo",2) == 3);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
string s = "hello";
|
||||
string t;
|
||||
foreach (c;codePoints(s))
|
||||
{
|
||||
t ~= cast(char) c;
|
||||
}
|
||||
assert(s == t);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
char[] a;
|
||||
foreach (c;codeUnits!(char)(cast(dchar)'\u20AC'))
|
||||
{
|
||||
a ~= c;
|
||||
}
|
||||
assert(a.length == 3);
|
||||
assert(a[0] == 0xE2);
|
||||
assert(a[1] == 0x82);
|
||||
assert(a[2] == 0xAC);
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
wstring ws;
|
||||
// transcode from UTF-8 to UTF-16
|
||||
transcode("hello world",ws);
|
||||
assert(ws == "hello world"w);
|
||||
|
||||
Latin1String ls;
|
||||
// transcode from UTF-16 to ISO-8859-1
|
||||
transcode(ws, ls);
|
||||
assert(ls == "hello world");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.encoding;
|
||||
|
||||
import std.format : format;
|
||||
|
||||
auto ts = dchar(0x0000FEFF) ~ "Hello World"d;
|
||||
|
||||
auto entry = getBOM(cast(ubyte[]) ts);
|
||||
version (BigEndian)
|
||||
{
|
||||
assert(entry.schema == BOM.utf32be, format("%s", entry.schema));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert(entry.schema == BOM.utf32le, format("%s", entry.schema));
|
||||
}
|
||||
}
|
||||
|
543
libphobos/testsuite/libphobos.phobos/std_exception.d
Normal file
543
libphobos/testsuite/libphobos.phobos/std_exception.d
Normal file
|
@ -0,0 +1,543 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import core.stdc.stdlib : malloc, free;
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.iteration : map, splitter;
|
||||
import std.algorithm.searching : endsWith;
|
||||
import std.conv : ConvException, to;
|
||||
import std.range : front, retro;
|
||||
|
||||
// use enforce like assert
|
||||
int a = 3;
|
||||
enforce(a > 2, "a needs to be higher than 2.");
|
||||
|
||||
// enforce can throw a custom exception
|
||||
enforce!ConvException(a > 2, "a needs to be higher than 2.");
|
||||
|
||||
// enforce will return it's input
|
||||
enum size = 42;
|
||||
auto memory = enforce(malloc(size), "malloc failed")[0 .. size];
|
||||
scope(exit) free(memory.ptr);
|
||||
|
||||
// collectException can be used to test for exceptions
|
||||
Exception e = collectException("abc".to!int);
|
||||
assert(e.file.endsWith("conv.d"));
|
||||
|
||||
// and just for the exception message
|
||||
string msg = collectExceptionMsg("abc".to!int);
|
||||
assert(msg == "Unexpected 'a' when converting from type string to type int");
|
||||
|
||||
// assertThrown can be used to assert that an exception is thrown
|
||||
assertThrown!ConvException("abc".to!int);
|
||||
|
||||
// ifThrown can be used to provide a default value if an exception is thrown
|
||||
assert("x".to!int().ifThrown(0) == 0);
|
||||
|
||||
// handle is a more advanced version of ifThrown for ranges
|
||||
auto r = "12,1337z32,54".splitter(',').map!(a => to!int(a));
|
||||
auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
|
||||
assert(h.equal([12, 0, 54]));
|
||||
assertThrown!ConvException(h.retro.equal([54, 0, 12]));
|
||||
|
||||
// basicExceptionCtors avoids the boilerplate when creating custom exceptions
|
||||
static class MeaCulpa : Exception
|
||||
{
|
||||
mixin basicExceptionCtors;
|
||||
}
|
||||
e = collectException((){throw new MeaCulpa("diagnostic message");}());
|
||||
assert(e.msg == "diagnostic message");
|
||||
assert(e.file == __FILE__);
|
||||
assert(e.line == __LINE__ - 3);
|
||||
|
||||
// assumeWontThrow can be used to cast throwing code into `nothrow`
|
||||
void exceptionFreeCode() nothrow
|
||||
{
|
||||
// auto-decoding only throws if an invalid UTF char is given
|
||||
assumeWontThrow("abc".front);
|
||||
}
|
||||
|
||||
// assumeUnique can be used to cast mutable instance to an `immutable` one
|
||||
// use with care
|
||||
char[] str = " mutable".dup;
|
||||
str[0 .. 2] = "im";
|
||||
immutable res = assumeUnique(str);
|
||||
assert(res == "immutable");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import core.exception : AssertError;
|
||||
|
||||
import std.string;
|
||||
assertNotThrown!StringException(enforce!StringException(true, "Error!"));
|
||||
|
||||
//Exception is the default.
|
||||
assertNotThrown(enforce!StringException(true, "Error!"));
|
||||
|
||||
assert(collectExceptionMsg!AssertError(assertNotThrown!StringException(
|
||||
enforce!StringException(false, "Error!"))) ==
|
||||
`assertNotThrown failed: StringException was thrown: Error!`);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import core.exception : AssertError;
|
||||
import std.string;
|
||||
|
||||
assertThrown!StringException(enforce!StringException(false, "Error!"));
|
||||
|
||||
//Exception is the default.
|
||||
assertThrown(enforce!StringException(false, "Error!"));
|
||||
|
||||
assert(collectExceptionMsg!AssertError(assertThrown!StringException(
|
||||
enforce!StringException(true, "Error!"))) ==
|
||||
`assertThrown failed: No StringException was thrown.`);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import core.stdc.stdlib : malloc, free;
|
||||
import std.conv : ConvException, to;
|
||||
|
||||
// use enforce like assert
|
||||
int a = 3;
|
||||
enforce(a > 2, "a needs to be higher than 2.");
|
||||
|
||||
// enforce can throw a custom exception
|
||||
enforce!ConvException(a > 2, "a needs to be higher than 2.");
|
||||
|
||||
// enforce will return it's input
|
||||
enum size = 42;
|
||||
auto memory = enforce(malloc(size), "malloc failed")[0 .. size];
|
||||
scope(exit) free(memory.ptr);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
assertNotThrown(enforce(true, new Exception("this should not be thrown")));
|
||||
assertThrown(enforce(false, new Exception("this should be thrown")));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
assert(enforce(123) == 123);
|
||||
|
||||
try
|
||||
{
|
||||
enforce(false, "error");
|
||||
assert(false);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
assert(e.msg == "error");
|
||||
assert(e.file == __FILE__);
|
||||
assert(e.line == __LINE__-7);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import std.conv : ConvException;
|
||||
alias convEnforce = enforce!ConvException;
|
||||
assertNotThrown(convEnforce(true));
|
||||
assertThrown!ConvException(convEnforce(false, "blah"));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import core.stdc.stdio : fclose, fgets, fopen;
|
||||
import std.file : thisExePath;
|
||||
import std.string : toStringz;
|
||||
|
||||
auto f = fopen(thisExePath.toStringz, "r").errnoEnforce;
|
||||
scope(exit) fclose(f);
|
||||
char[100] buf;
|
||||
auto line = fgets(buf.ptr, buf.length, f);
|
||||
enforce(line !is null); // expect a non-empty line
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
int b;
|
||||
int foo() { throw new Exception("blah"); }
|
||||
assert(collectException(foo(), b));
|
||||
|
||||
version (D_NoBoundsChecks) {}
|
||||
else
|
||||
{
|
||||
// check for out of bounds error
|
||||
int[] a = new int[3];
|
||||
import core.exception : RangeError;
|
||||
assert(collectException!RangeError(a[4], b));
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
int foo() { throw new Exception("blah"); }
|
||||
assert(collectException(foo()).msg == "blah");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
void throwFunc() { throw new Exception("My Message."); }
|
||||
assert(collectExceptionMsg(throwFunc()) == "My Message.");
|
||||
|
||||
void nothrowFunc() {}
|
||||
assert(collectExceptionMsg(nothrowFunc()) is null);
|
||||
|
||||
void throwEmptyFunc() { throw new Exception(""); }
|
||||
assert(collectExceptionMsg(throwEmptyFunc()) == emptyExceptionMsg);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
int[] arr = new int[1];
|
||||
auto arr1 = arr.assumeUnique;
|
||||
static assert(is(typeof(arr1) == immutable(int)[]));
|
||||
assert(arr == null);
|
||||
assert(arr1 == [0]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
int[string] arr = ["a":1];
|
||||
auto arr1 = arr.assumeUnique;
|
||||
static assert(is(typeof(arr1) == immutable(int[string])));
|
||||
assert(arr == null);
|
||||
assert(arr1.keys == ["a"]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import std.math.algebraic : sqrt;
|
||||
|
||||
// This function may throw.
|
||||
int squareRoot(int x)
|
||||
{
|
||||
if (x < 0)
|
||||
throw new Exception("Tried to take root of negative number");
|
||||
return cast(int) sqrt(cast(double) x);
|
||||
}
|
||||
|
||||
// This function never throws.
|
||||
int computeLength(int x, int y) nothrow
|
||||
{
|
||||
// Since x*x + y*y is always positive, we can safely assume squareRoot
|
||||
// won't throw, and use it to implement this nothrow function. If it
|
||||
// does throw (e.g., if x*x + y*y overflows a 32-bit value), then the
|
||||
// program will terminate.
|
||||
return assumeWontThrow(squareRoot(x*x + y*y));
|
||||
}
|
||||
|
||||
assert(computeLength(3, 4) == 5);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
int i = 0;
|
||||
int* p = null;
|
||||
assert(!p.doesPointTo(i));
|
||||
p = &i;
|
||||
assert( p.doesPointTo(i));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
struct S
|
||||
{
|
||||
int v;
|
||||
int* p;
|
||||
}
|
||||
int i;
|
||||
auto s = S(0, &i);
|
||||
|
||||
// structs and unions "own" their members
|
||||
// pointsTo will answer true if one of the members pointsTo.
|
||||
assert(!s.doesPointTo(s.v)); //s.v is just v member of s, so not pointed.
|
||||
assert( s.p.doesPointTo(i)); //i is pointed by s.p.
|
||||
assert( s .doesPointTo(i)); //which means i is pointed by s itself.
|
||||
|
||||
// Unions will behave exactly the same. Points to will check each "member"
|
||||
// individually, even if they share the same memory
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
int i;
|
||||
// trick the compiler when initializing slice
|
||||
// https://issues.dlang.org/show_bug.cgi?id=18637
|
||||
int* p = &i;
|
||||
int[] slice = [0, 1, 2, 3, 4];
|
||||
int[5] arr = [0, 1, 2, 3, 4];
|
||||
int*[] slicep = [p];
|
||||
int*[1] arrp = [&i];
|
||||
|
||||
// A slice points to all of its members:
|
||||
assert( slice.doesPointTo(slice[3]));
|
||||
assert(!slice[0 .. 2].doesPointTo(slice[3])); // Object 3 is outside of the
|
||||
// slice [0 .. 2]
|
||||
|
||||
// Note that a slice will not take into account what its members point to.
|
||||
assert( slicep[0].doesPointTo(i));
|
||||
assert(!slicep .doesPointTo(i));
|
||||
|
||||
// static arrays are objects that own their members, just like structs:
|
||||
assert(!arr.doesPointTo(arr[0])); // arr[0] is just a member of arr, so not
|
||||
// pointed.
|
||||
assert( arrp[0].doesPointTo(i)); // i is pointed by arrp[0].
|
||||
assert( arrp .doesPointTo(i)); // which means i is pointed by arrp
|
||||
// itself.
|
||||
|
||||
// Notice the difference between static and dynamic arrays:
|
||||
assert(!arr .doesPointTo(arr[0]));
|
||||
assert( arr[].doesPointTo(arr[0]));
|
||||
assert( arrp .doesPointTo(i));
|
||||
assert(!arrp[].doesPointTo(i));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
class C
|
||||
{
|
||||
this(int* p){this.p = p;}
|
||||
int* p;
|
||||
}
|
||||
int i;
|
||||
C a = new C(&i);
|
||||
C b = a;
|
||||
|
||||
// Classes are a bit particular, as they are treated like simple pointers
|
||||
// to a class payload.
|
||||
assert( a.p.doesPointTo(i)); // a.p points to i.
|
||||
assert(!a .doesPointTo(i)); // Yet a itself does not point i.
|
||||
|
||||
//To check the class payload itself, iterate on its members:
|
||||
()
|
||||
{
|
||||
import std.traits : Fields;
|
||||
|
||||
foreach (index, _; Fields!C)
|
||||
if (doesPointTo(a.tupleof[index], i))
|
||||
return;
|
||||
assert(0);
|
||||
}();
|
||||
|
||||
// To check if a class points a specific payload, a direct memmory check
|
||||
// can be done:
|
||||
auto aLoc = cast(ubyte[__traits(classInstanceSize, C)]*) a;
|
||||
assert(b.doesPointTo(*aLoc)); // b points to where a is pointing
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import core.stdc.errno : EAGAIN;
|
||||
auto ex = new ErrnoException("oh no", EAGAIN);
|
||||
assert(ex.errno == EAGAIN);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import core.stdc.errno : errno, EAGAIN;
|
||||
|
||||
auto old = errno;
|
||||
scope(exit) errno = old;
|
||||
|
||||
// fake that errno got set by the callee
|
||||
errno = EAGAIN;
|
||||
auto ex = new ErrnoException("oh no");
|
||||
assert(ex.errno == EAGAIN);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import std.conv : to;
|
||||
assert("x".to!int.ifThrown(0) == 0);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import std.conv : ConvException, to;
|
||||
string s = "true";
|
||||
assert(s.to!int.ifThrown(cast(int) s.to!double)
|
||||
.ifThrown(cast(int) s.to!bool) == 1);
|
||||
|
||||
s = "2.0";
|
||||
assert(s.to!int.ifThrown(cast(int) s.to!double)
|
||||
.ifThrown(cast(int) s.to!bool) == 2);
|
||||
|
||||
// Respond differently to different types of errors
|
||||
alias orFallback = (lazy a) => a.ifThrown!ConvException("not a number")
|
||||
.ifThrown!Exception("number too small");
|
||||
|
||||
assert(orFallback(enforce("x".to!int < 1).to!string) == "not a number");
|
||||
assert(orFallback(enforce("2".to!int < 1).to!string) == "number too small");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
// null and new Object have a common type(Object).
|
||||
static assert(is(typeof(null.ifThrown(new Object())) == Object));
|
||||
static assert(is(typeof((new Object()).ifThrown(null)) == Object));
|
||||
|
||||
// 1 and new Object do not have a common type.
|
||||
static assert(!__traits(compiles, 1.ifThrown(new Object())));
|
||||
static assert(!__traits(compiles, (new Object()).ifThrown(1)));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import std.format : format;
|
||||
assert("%s".format.ifThrown!Exception(e => typeid(e).name) == "std.format.FormatException");
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.iteration : map, splitter;
|
||||
import std.conv : to, ConvException;
|
||||
|
||||
auto s = "12,1337z32,54,2,7,9,1z,6,8";
|
||||
|
||||
// The next line composition will throw when iterated
|
||||
// as some elements of the input do not convert to integer
|
||||
auto r = s.splitter(',').map!(a => to!int(a));
|
||||
|
||||
// Substitute 0 for cases of ConvException
|
||||
auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
|
||||
assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : retro;
|
||||
import std.utf : UTFException;
|
||||
|
||||
auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
|
||||
|
||||
auto handled = str.handle!(UTFException, RangePrimitive.access,
|
||||
(e, r) => ' '); // Replace invalid code points with spaces
|
||||
|
||||
assert(handled.equal("hello world")); // `front` is handled,
|
||||
assert(handled.retro.equal("dlrow olleh")); // as well as `back`
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.iteration : map, splitter;
|
||||
import std.conv : to, ConvException;
|
||||
|
||||
auto s = "12,1337z32,54,2,7,9,1z,6,8";
|
||||
|
||||
// The next line composition will throw when iterated
|
||||
// as some elements of the input do not convert to integer
|
||||
auto r = s.splitter(',').map!(a => to!int(a));
|
||||
|
||||
// Substitute 0 for cases of ConvException
|
||||
auto h = r.handle!(ConvException, RangePrimitive.front, (e, r) => 0);
|
||||
assert(h.equal([12, 0, 54, 2, 7, 9, 0, 6, 8]));
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : retro;
|
||||
import std.utf : UTFException;
|
||||
|
||||
auto str = "hello\xFFworld"; // 0xFF is an invalid UTF-8 code unit
|
||||
|
||||
auto handled = str.handle!(UTFException, RangePrimitive.access,
|
||||
(e, r) => ' '); // Replace invalid code points with spaces
|
||||
|
||||
assert(handled.equal("hello world")); // `front` is handled,
|
||||
assert(handled.retro.equal("dlrow olleh")); // as well as `back`
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
class MeaCulpa: Exception
|
||||
{
|
||||
///
|
||||
mixin basicExceptionCtors;
|
||||
}
|
||||
|
||||
try
|
||||
throw new MeaCulpa("test");
|
||||
catch (MeaCulpa e)
|
||||
{
|
||||
assert(e.msg == "test");
|
||||
assert(e.file == __FILE__);
|
||||
assert(e.line == __LINE__ - 5);
|
||||
}
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.exception;
|
||||
|
||||
class TestException : Exception { mixin basicExceptionCtors; }
|
||||
auto e = new Exception("msg");
|
||||
auto te1 = new TestException("foo");
|
||||
auto te2 = new TestException("foo", e);
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.affix_allocator;
|
||||
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
// One word before and after each allocation.
|
||||
alias A = AffixAllocator!(Mallocator, size_t, size_t);
|
||||
auto b = A.instance.allocate(11);
|
||||
A.instance.prefix(b) = 0xCAFE_BABE;
|
||||
A.instance.suffix(b) = 0xDEAD_BEEF;
|
||||
assert(A.instance.prefix(b) == 0xCAFE_BABE
|
||||
&& A.instance.suffix(b) == 0xDEAD_BEEF);
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.aligned_block_list;
|
||||
|
||||
import std.experimental.allocator.building_blocks.ascending_page_allocator : AscendingPageAllocator;
|
||||
import std.experimental.allocator.building_blocks.segregator : Segregator;
|
||||
import std.experimental.allocator.building_blocks.bitmapped_block : BitmappedBlock;
|
||||
import std.typecons : Ternary;
|
||||
|
||||
/*
|
||||
In this example we use 'AlignedBlockList' in conjunction with other allocators
|
||||
in order to create a more complex allocator.
|
||||
|
||||
The 'SuperAllocator' uses a 'Segregator' to distribute allocations to sub-allocators,
|
||||
based on the requested size.
|
||||
|
||||
Each sub-allocator is represented by an 'AlignedBlockList' of 'BitmappedBlocks'.
|
||||
Each 'AlignedBlockList' draws memory from a root allocator which in this case is an 'AscendingPageAllocator'
|
||||
|
||||
Such an allocator not only provides good performance, but also a low degree of memory fragmentation.
|
||||
*/
|
||||
alias SuperAllocator = Segregator!(
|
||||
32,
|
||||
AlignedBlockList!(BitmappedBlock!32, AscendingPageAllocator*, 1 << 12),
|
||||
Segregator!(
|
||||
|
||||
64,
|
||||
AlignedBlockList!(BitmappedBlock!64, AscendingPageAllocator*, 1 << 12),
|
||||
Segregator!(
|
||||
|
||||
128,
|
||||
AlignedBlockList!(BitmappedBlock!128, AscendingPageAllocator*, 1 << 12),
|
||||
AscendingPageAllocator*
|
||||
)));
|
||||
|
||||
SuperAllocator a;
|
||||
auto pageAlloc = AscendingPageAllocator(128 * 4096);
|
||||
|
||||
// Set the parent allocator for all the sub allocators
|
||||
a.allocatorForSize!256 = &pageAlloc;
|
||||
a.allocatorForSize!128.parent = &pageAlloc;
|
||||
a.allocatorForSize!64.parent = &pageAlloc;
|
||||
a.allocatorForSize!32.parent = &pageAlloc;
|
||||
|
||||
enum testNum = 10;
|
||||
void[][testNum] buf;
|
||||
|
||||
// Allocations of size 32 will go to the first 'AlignedBlockList'
|
||||
foreach (j; 0 .. testNum)
|
||||
{
|
||||
buf[j] = a.allocate(32);
|
||||
assert(buf[j].length == 32);
|
||||
|
||||
// This is owned by the first 'AlignedBlockList'
|
||||
assert(a.allocatorForSize!32.owns(buf[j]) == Ternary.yes);
|
||||
}
|
||||
|
||||
// Free the memory
|
||||
foreach (j; 0 .. testNum)
|
||||
assert(a.deallocate(buf[j]));
|
||||
|
||||
// Allocations of size 64 will go to the second 'AlignedBlockList'
|
||||
foreach (j; 0 .. testNum)
|
||||
{
|
||||
buf[j] = a.allocate(64);
|
||||
assert(buf[j].length == 64);
|
||||
|
||||
// This is owned by the second 'AlignedBlockList'
|
||||
assert(a.allocatorForSize!64.owns(buf[j]) == Ternary.yes);
|
||||
}
|
||||
|
||||
// Free the memory
|
||||
foreach (j; 0 .. testNum)
|
||||
assert(a.deallocate(buf[j]));
|
||||
|
||||
// Allocations of size 128 will go to the third 'AlignedBlockList'
|
||||
foreach (j; 0 .. testNum)
|
||||
{
|
||||
buf[j] = a.allocate(128);
|
||||
assert(buf[j].length == 128);
|
||||
|
||||
// This is owned by the third 'AlignedBlockList'
|
||||
assert(a.allocatorForSize!128.owns(buf[j]) == Ternary.yes);
|
||||
}
|
||||
|
||||
// Free the memory
|
||||
foreach (j; 0 .. testNum)
|
||||
assert(a.deallocate(buf[j]));
|
||||
|
||||
// Allocations which exceed 128, will go to the 'AscendingPageAllocator*'
|
||||
void[] b = a.allocate(256);
|
||||
assert(b.length == 256);
|
||||
a.deallocate(b);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.aligned_block_list;
|
||||
|
||||
import std.experimental.allocator.building_blocks.region : SharedBorrowedRegion;
|
||||
import std.experimental.allocator.building_blocks.ascending_page_allocator : SharedAscendingPageAllocator;
|
||||
import std.experimental.allocator.building_blocks.null_allocator : NullAllocator;
|
||||
import core.thread : ThreadGroup;
|
||||
|
||||
enum numThreads = 8;
|
||||
enum size = 2048;
|
||||
enum maxIter = 10;
|
||||
|
||||
/*
|
||||
In this example we use 'SharedAlignedBlockList' together with
|
||||
'SharedBorrowedRegion', in order to create a fast, thread-safe allocator.
|
||||
*/
|
||||
alias SuperAllocator = SharedAlignedBlockList!(
|
||||
SharedBorrowedRegion!(1),
|
||||
SharedAscendingPageAllocator,
|
||||
4096);
|
||||
|
||||
SuperAllocator a;
|
||||
// The 'SuperAllocator' will draw memory from a 'SharedAscendingPageAllocator'
|
||||
a.parent = SharedAscendingPageAllocator(4096 * 1024);
|
||||
|
||||
// Launch 'numThreads', each performing allocations
|
||||
void fun()
|
||||
{
|
||||
foreach (i; 0 .. maxIter)
|
||||
{
|
||||
void[] b = a.allocate(size);
|
||||
assert(b.length == size);
|
||||
}
|
||||
}
|
||||
|
||||
auto tg = new ThreadGroup;
|
||||
foreach (i; 0 .. numThreads)
|
||||
{
|
||||
tg.create(&fun);
|
||||
}
|
||||
tg.joinAll();
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.allocator_list;
|
||||
|
||||
import std.algorithm.comparison : max;
|
||||
import std.experimental.allocator.building_blocks.free_list : ContiguousFreeList;
|
||||
import std.experimental.allocator.building_blocks.null_allocator : NullAllocator;
|
||||
import std.experimental.allocator.building_blocks.region : Region;
|
||||
import std.experimental.allocator.building_blocks.segregator : Segregator;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.experimental.allocator.mmap_allocator : MmapAllocator;
|
||||
|
||||
// Ouroboros allocator list based upon 4MB regions, fetched directly from
|
||||
// mmap. All memory is released upon destruction.
|
||||
alias A1 = AllocatorList!((n) => Region!MmapAllocator(max(n, 1024 * 4096)),
|
||||
NullAllocator);
|
||||
|
||||
// Allocator list based upon 4MB regions, fetched from the garbage
|
||||
// collector. All memory is released upon destruction.
|
||||
alias A2 = AllocatorList!((n) => Region!GCAllocator(max(n, 1024 * 4096)));
|
||||
|
||||
// Ouroboros allocator list based upon 4MB regions, fetched from the garbage
|
||||
// collector. Memory is left to the collector.
|
||||
alias A3 = AllocatorList!(
|
||||
(n) => Region!NullAllocator(new ubyte[max(n, 1024 * 4096)]),
|
||||
NullAllocator);
|
||||
|
||||
// Allocator list that creates one freelist for all objects
|
||||
alias A4 =
|
||||
Segregator!(
|
||||
64, AllocatorList!(
|
||||
(n) => ContiguousFreeList!(NullAllocator, 0, 64)(
|
||||
cast(ubyte[])(GCAllocator.instance.allocate(4096)))),
|
||||
GCAllocator);
|
||||
|
||||
A4 a;
|
||||
auto small = a.allocate(64);
|
||||
assert(small);
|
||||
a.deallocate(small);
|
||||
auto b1 = a.allocate(1024 * 8192);
|
||||
assert(b1 !is null); // still works due to overdimensioning
|
||||
b1 = a.allocate(1024 * 10);
|
||||
assert(b1.length == 1024 * 10);
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
@system @nogc nothrow unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.ascending_page_allocator;
|
||||
|
||||
import core.memory : pageSize;
|
||||
|
||||
size_t numPages = 100;
|
||||
void[] buf;
|
||||
void[] prevBuf = null;
|
||||
AscendingPageAllocator a = AscendingPageAllocator(numPages * pageSize);
|
||||
|
||||
foreach (i; 0 .. numPages)
|
||||
{
|
||||
// Allocation is rounded up to page size
|
||||
buf = a.allocate(pageSize - 100);
|
||||
assert(buf.length == pageSize - 100);
|
||||
|
||||
// Allocations are served at increasing addresses
|
||||
if (prevBuf)
|
||||
assert(prevBuf.ptr + pageSize == buf.ptr);
|
||||
|
||||
assert(a.deallocate(buf));
|
||||
prevBuf = buf;
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.ascending_page_allocator;
|
||||
|
||||
import core.memory : pageSize;
|
||||
import core.thread : ThreadGroup;
|
||||
|
||||
enum numThreads = 100;
|
||||
shared SharedAscendingPageAllocator a = SharedAscendingPageAllocator(pageSize * numThreads);
|
||||
|
||||
void fun()
|
||||
{
|
||||
void[] b = a.allocate(pageSize);
|
||||
assert(b.length == pageSize);
|
||||
|
||||
assert(a.deallocate(b));
|
||||
}
|
||||
|
||||
auto tg = new ThreadGroup;
|
||||
foreach (i; 0 .. numThreads)
|
||||
{
|
||||
tg.create(&fun);
|
||||
}
|
||||
tg.joinAll();
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.bitmapped_block;
|
||||
|
||||
// Create a block allocator on top of a 10KB stack region.
|
||||
import std.experimental.allocator.building_blocks.region : InSituRegion;
|
||||
import std.traits : hasMember;
|
||||
InSituRegion!(10_240, 64) r;
|
||||
auto a = BitmappedBlock!(64, 64)(cast(ubyte[])(r.allocateAll()));
|
||||
static assert(hasMember!(InSituRegion!(10_240, 64), "allocateAll"));
|
||||
const b = a.allocate(100);
|
||||
assert(b.length == 100);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.bitmapped_block;
|
||||
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
import std.typecons : Flag, Yes;
|
||||
|
||||
enum blockSize = 64;
|
||||
enum numBlocks = 10;
|
||||
|
||||
// The 'BitmappedBlock' is implicitly instantiated with Yes.multiblock
|
||||
auto a = BitmappedBlock!(blockSize, 8, Mallocator, Yes.multiblock)(numBlocks * blockSize);
|
||||
|
||||
// Instantiated with Yes.multiblock, can allocate more than one block at a time
|
||||
void[] buf = a.allocate(2 * blockSize);
|
||||
assert(buf.length == 2 * blockSize);
|
||||
assert(a.deallocate(buf));
|
||||
|
||||
// Can also allocate less than one block
|
||||
buf = a.allocate(blockSize / 2);
|
||||
assert(buf.length == blockSize / 2);
|
||||
|
||||
// Expands inside the same block
|
||||
assert(a.expand(buf, blockSize / 2));
|
||||
assert(buf.length == blockSize);
|
||||
|
||||
// If Yes.multiblock, can expand past the size of a single block
|
||||
assert(a.expand(buf, 3 * blockSize));
|
||||
assert(buf.length == 4 * blockSize);
|
||||
assert(a.deallocate(buf));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.bitmapped_block;
|
||||
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
import std.typecons : Flag, No;
|
||||
|
||||
enum blockSize = 64;
|
||||
auto a = BitmappedBlock!(blockSize, 8, Mallocator, No.multiblock)(1024 * blockSize);
|
||||
|
||||
// Since instantiated with No.multiblock, can only allocate at most the block size
|
||||
void[] buf = a.allocate(blockSize + 1);
|
||||
assert(buf is null);
|
||||
|
||||
buf = a.allocate(blockSize);
|
||||
assert(buf.length == blockSize);
|
||||
assert(a.deallocate(buf));
|
||||
|
||||
// This is also fine, because it's less than the block size
|
||||
buf = a.allocate(blockSize / 2);
|
||||
assert(buf.length == blockSize / 2);
|
||||
|
||||
// Can expand the buffer until its length is at most 64
|
||||
assert(a.expand(buf, blockSize / 2));
|
||||
assert(buf.length == blockSize);
|
||||
|
||||
// Cannot expand anymore
|
||||
assert(!a.expand(buf, 1));
|
||||
assert(a.deallocate(buf));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.bitmapped_block;
|
||||
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
import std.experimental.allocator.common : platformAlignment;
|
||||
import std.typecons : Flag, Yes, No;
|
||||
|
||||
// Create 'numThreads' threads, each allocating in parallel a chunk of memory
|
||||
static void testAlloc(Allocator)(ref Allocator a, size_t allocSize)
|
||||
{
|
||||
import core.thread : ThreadGroup;
|
||||
import std.algorithm.sorting : sort;
|
||||
import core.internal.spinlock : SpinLock;
|
||||
|
||||
SpinLock lock = SpinLock(SpinLock.Contention.brief);
|
||||
enum numThreads = 10;
|
||||
void[][numThreads] buf;
|
||||
size_t count = 0;
|
||||
|
||||
// Each threads allocates 'allocSize'
|
||||
void fun()
|
||||
{
|
||||
void[] b = a.allocate(allocSize);
|
||||
assert(b.length == allocSize);
|
||||
|
||||
lock.lock();
|
||||
scope(exit) lock.unlock();
|
||||
|
||||
buf[count] = b;
|
||||
count++;
|
||||
}
|
||||
|
||||
auto tg = new ThreadGroup;
|
||||
foreach (i; 0 .. numThreads)
|
||||
{
|
||||
tg.create(&fun);
|
||||
}
|
||||
tg.joinAll();
|
||||
|
||||
// Sorting the allocations made by each thread, we expect the buffers to be
|
||||
// adjacent inside the SharedBitmappedBlock
|
||||
sort!((a, b) => a.ptr < b.ptr)(buf[0 .. numThreads]);
|
||||
foreach (i; 0 .. numThreads - 1)
|
||||
{
|
||||
assert(buf[i].ptr + a.goodAllocSize(buf[i].length) <= buf[i + 1].ptr);
|
||||
}
|
||||
|
||||
// Deallocate everything
|
||||
foreach (i; 0 .. numThreads)
|
||||
{
|
||||
assert(a.deallocate(buf[i]));
|
||||
}
|
||||
}
|
||||
|
||||
enum blockSize = 64;
|
||||
auto alloc1 = SharedBitmappedBlock!(blockSize, platformAlignment, Mallocator, Yes.multiblock)(1024 * 1024);
|
||||
auto alloc2 = SharedBitmappedBlock!(blockSize, platformAlignment, Mallocator, No.multiblock)(1024 * 1024);
|
||||
testAlloc(alloc1, 2 * blockSize);
|
||||
testAlloc(alloc2, blockSize);
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.bucketizer;
|
||||
|
||||
import std.algorithm.comparison : max;
|
||||
import std.experimental.allocator.building_blocks.allocator_list : AllocatorList;
|
||||
import std.experimental.allocator.building_blocks.free_list : FreeList;
|
||||
import std.experimental.allocator.building_blocks.region : Region;
|
||||
import std.experimental.allocator.common : unbounded;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
import std.typecons : Ternary;
|
||||
Bucketizer!(
|
||||
FreeList!(
|
||||
AllocatorList!(
|
||||
(size_t n) => Region!Mallocator(max(n, 1024 * 1024))),
|
||||
0, unbounded),
|
||||
65, 512, 64) a;
|
||||
auto b = a.allocate(400);
|
||||
assert(b.length == 400);
|
||||
assert(a.owns(b) == Ternary.yes);
|
||||
a.deallocate(b);
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.fallback_allocator;
|
||||
|
||||
import std.experimental.allocator.building_blocks.region : Region;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.typecons : Ternary;
|
||||
auto a = fallbackAllocator(Region!GCAllocator(1024), GCAllocator.instance);
|
||||
auto b1 = a.allocate(1020);
|
||||
assert(b1.length == 1020);
|
||||
assert(a.primary.owns(b1) == Ternary.yes);
|
||||
auto b2 = a.allocate(10);
|
||||
assert(b2.length == 10);
|
||||
assert(a.primary.owns(b2) == Ternary.no);
|
||||
}
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.free_list;
|
||||
|
||||
import std.experimental.allocator.building_blocks.allocator_list
|
||||
: AllocatorList;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
|
||||
import std.experimental.allocator.common : unbounded;
|
||||
|
||||
alias ScalableFreeList = AllocatorList!((n) =>
|
||||
ContiguousFreeList!(GCAllocator, 0, unbounded)(4096)
|
||||
);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.free_list;
|
||||
|
||||
import std.experimental.allocator.common : chooseAtRuntime;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
|
||||
shared SharedFreeList!(Mallocator, chooseAtRuntime, chooseAtRuntime) a;
|
||||
a.setBounds(64, 128);
|
||||
assert(a.max == 128);
|
||||
assert(a.min == 64);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.free_list;
|
||||
|
||||
import std.experimental.allocator.common : chooseAtRuntime;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
|
||||
shared SharedFreeList!(Mallocator, 50, 50, chooseAtRuntime) a;
|
||||
// Set the maxSize first so setting the minSize doesn't throw
|
||||
a.approxMaxLength = 128;
|
||||
assert(a.approxMaxLength == 128);
|
||||
a.approxMaxLength = 1024;
|
||||
assert(a.approxMaxLength == 1024);
|
||||
a.approxMaxLength = 1;
|
||||
assert(a.approxMaxLength == 1);
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.kernighan_ritchie;
|
||||
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
auto alloc = KRRegion!GCAllocator(1024 * 64);
|
||||
const b1 = alloc.allocate(2048);
|
||||
assert(b1.length == 2048);
|
||||
const b2 = alloc.allocateAll;
|
||||
assert(b2.length == 1024 * 62);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.kernighan_ritchie;
|
||||
|
||||
import std.experimental.allocator.building_blocks.fallback_allocator
|
||||
: fallbackAllocator;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.typecons : Ternary;
|
||||
// KRRegion fronting a general-purpose allocator
|
||||
align(KRRegion!().alignment) ubyte[1024 * 128] buf;
|
||||
auto alloc = fallbackAllocator(KRRegion!()(buf), GCAllocator.instance);
|
||||
auto b = alloc.allocate(100);
|
||||
assert(b.length == 100);
|
||||
assert((() pure nothrow @safe @nogc => alloc.primary.owns(b))() == Ternary.yes);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.kernighan_ritchie;
|
||||
|
||||
import std.algorithm.comparison : max;
|
||||
import std.experimental.allocator.building_blocks.allocator_list
|
||||
: AllocatorList;
|
||||
import std.experimental.allocator.mmap_allocator : MmapAllocator;
|
||||
AllocatorList!(n => KRRegion!MmapAllocator(max(n * 16, 1024 * 1024))) alloc;
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.quantizer;
|
||||
|
||||
import std.experimental.allocator.building_blocks.free_tree : FreeTree;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
|
||||
size_t roundUpToMultipleOf(size_t s, uint base)
|
||||
{
|
||||
auto rem = s % base;
|
||||
return rem ? s + base - rem : s;
|
||||
}
|
||||
|
||||
// Quantize small allocations to a multiple of cache line, large ones to a
|
||||
// multiple of page size
|
||||
alias MyAlloc = Quantizer!(
|
||||
FreeTree!GCAllocator,
|
||||
n => roundUpToMultipleOf(n, n <= 16_384 ? 64 : 4096));
|
||||
MyAlloc alloc;
|
||||
const buf = alloc.allocate(256);
|
||||
assert(buf.ptr);
|
||||
}
|
||||
|
|
@ -0,0 +1,90 @@
|
|||
@system nothrow unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.region;
|
||||
|
||||
import std.algorithm.comparison : max;
|
||||
import std.experimental.allocator.building_blocks.allocator_list
|
||||
: AllocatorList;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
import std.typecons : Ternary;
|
||||
// Create a scalable list of regions. Each gets at least 1MB at a time by
|
||||
// using malloc.
|
||||
auto batchAllocator = AllocatorList!(
|
||||
(size_t n) => Region!Mallocator(max(n, 1024 * 1024))
|
||||
)();
|
||||
assert(batchAllocator.empty == Ternary.yes);
|
||||
auto b = batchAllocator.allocate(101);
|
||||
assert(b.length == 101);
|
||||
assert(batchAllocator.empty == Ternary.no);
|
||||
// This will cause a second allocation
|
||||
b = batchAllocator.allocate(2 * 1024 * 1024);
|
||||
assert(b.length == 2 * 1024 * 1024);
|
||||
// Destructor will free the memory
|
||||
}
|
||||
|
||||
@system nothrow @nogc unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.region;
|
||||
|
||||
import std.typecons : Ternary;
|
||||
|
||||
ubyte[1024] store;
|
||||
auto myRegion = BorrowedRegion!(1)(store[]);
|
||||
|
||||
assert(myRegion.empty == Ternary.yes);
|
||||
assert(myRegion.available == store.length);
|
||||
|
||||
void[] b = myRegion.allocate(101);
|
||||
|
||||
assert(b.length == 101);
|
||||
assert(myRegion.empty == Ternary.no);
|
||||
assert(myRegion.owns(b) == Ternary.yes);
|
||||
assert(myRegion.available == store.length - b.length);
|
||||
|
||||
void[] b2 = myRegion.allocate(256);
|
||||
|
||||
// Can only free the most recent allocation
|
||||
assert(myRegion.deallocate(b) == false);
|
||||
assert(myRegion.deallocate(b2) == true);
|
||||
|
||||
myRegion.deallocateAll();
|
||||
|
||||
assert(myRegion.empty == Ternary.yes);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.region;
|
||||
|
||||
// 128KB region, allocated to x86's cache line
|
||||
InSituRegion!(128 * 1024, 16) r1;
|
||||
auto a1 = r1.allocate(101);
|
||||
assert(a1.length == 101);
|
||||
|
||||
// 128KB region, with fallback to the garbage collector.
|
||||
import std.experimental.allocator.building_blocks.fallback_allocator
|
||||
: FallbackAllocator;
|
||||
import std.experimental.allocator.building_blocks.free_list
|
||||
: FreeList;
|
||||
import std.experimental.allocator.building_blocks.bitmapped_block
|
||||
: BitmappedBlock;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
FallbackAllocator!(InSituRegion!(128 * 1024), GCAllocator) r2;
|
||||
const a2 = r2.allocate(102);
|
||||
assert(a2.length == 102);
|
||||
|
||||
// Reap with GC fallback.
|
||||
InSituRegion!(128 * 1024, 8) tmp3;
|
||||
FallbackAllocator!(BitmappedBlock!(64, 8), GCAllocator) r3;
|
||||
r3.primary = BitmappedBlock!(64, 8)(cast(ubyte[]) (tmp3.allocateAll()));
|
||||
const a3 = r3.allocate(103);
|
||||
assert(a3.length == 103);
|
||||
|
||||
// Reap/GC with a freelist for small objects up to 16 bytes.
|
||||
InSituRegion!(128 * 1024, 64) tmp4;
|
||||
FreeList!(FallbackAllocator!(BitmappedBlock!(64, 64), GCAllocator), 0, 16) r4;
|
||||
r4.parent.primary = BitmappedBlock!(64, 64)(cast(ubyte[]) (tmp4.allocateAll()));
|
||||
const a4 = r4.allocate(104);
|
||||
assert(a4.length == 104);
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.scoped_allocator;
|
||||
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
import std.typecons : Ternary;
|
||||
ScopedAllocator!Mallocator alloc;
|
||||
assert(alloc.empty == Ternary.yes);
|
||||
const b = alloc.allocate(10);
|
||||
assert(b.length == 10);
|
||||
assert(alloc.empty == Ternary.no);
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.segregator;
|
||||
|
||||
import std.experimental.allocator.building_blocks.free_list : FreeList;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
alias A =
|
||||
Segregator!(
|
||||
1024 * 4,
|
||||
Segregator!(
|
||||
128, FreeList!(Mallocator, 0, 128),
|
||||
GCAllocator),
|
||||
Segregator!(
|
||||
1024 * 1024, Mallocator,
|
||||
GCAllocator)
|
||||
);
|
||||
A a;
|
||||
auto b = a.allocate(200);
|
||||
assert(b.length == 200);
|
||||
a.deallocate(b);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.segregator;
|
||||
|
||||
import std.experimental.allocator.building_blocks.free_list : FreeList;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
alias A =
|
||||
Segregator!(
|
||||
128, FreeList!(Mallocator, 0, 128),
|
||||
1024 * 4, GCAllocator,
|
||||
1024 * 1024, Mallocator,
|
||||
GCAllocator
|
||||
);
|
||||
A a;
|
||||
auto b = a.allocate(201);
|
||||
assert(b.length == 201);
|
||||
a.deallocate(b);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.stats_collector;
|
||||
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.experimental.allocator.building_blocks.free_list : FreeList;
|
||||
alias Allocator = StatsCollector!(GCAllocator, Options.bytesUsed);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.building_blocks.stats_collector;
|
||||
|
||||
import std.experimental.allocator.building_blocks.free_list : FreeList;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
alias Allocator = StatsCollector!(GCAllocator, Options.all, Options.all);
|
||||
|
||||
Allocator alloc;
|
||||
auto b = alloc.allocate(10);
|
||||
alloc.reallocate(b, 20);
|
||||
alloc.deallocate(b);
|
||||
|
||||
import std.file : deleteme, remove;
|
||||
import std.range : walkLength;
|
||||
import std.stdio : File;
|
||||
|
||||
auto f = deleteme ~ "-dlang.std.experimental.allocator.stats_collector.txt";
|
||||
scope(exit) remove(f);
|
||||
Allocator.reportPerCallStatistics(File(f, "w"));
|
||||
alloc.reportStatistics(File(f, "a"));
|
||||
assert(File(f).byLine.walkLength == 24);
|
||||
}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
@safe @nogc nothrow pure unittest
|
||||
{
|
||||
import std.experimental.allocator.common;
|
||||
|
||||
import std.experimental.allocator.building_blocks.null_allocator : NullAllocator;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.experimental.allocator.mmap_allocator : MmapAllocator;
|
||||
static assert(isAllocator!NullAllocator);
|
||||
static assert(isAllocator!Mallocator);
|
||||
static assert(isAllocator!GCAllocator);
|
||||
static assert(isAllocator!MmapAllocator);
|
||||
static assert(!isAllocator!int);
|
||||
}
|
||||
|
||||
@safe @nogc nothrow pure unittest
|
||||
{
|
||||
import std.experimental.allocator.common;
|
||||
|
||||
import std.experimental.allocator.building_blocks.null_allocator : NullAllocator;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.experimental.allocator.mmap_allocator : MmapAllocator;
|
||||
struct S
|
||||
{
|
||||
mixin AllocatorState!NullAllocator n;
|
||||
mixin AllocatorState!GCAllocator g;
|
||||
mixin AllocatorState!Mallocator m;
|
||||
mixin AllocatorState!MmapAllocator p;
|
||||
}
|
||||
static assert(S.sizeof == 1);
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
pure @system unittest
|
||||
{
|
||||
import std.experimental.allocator.gc_allocator;
|
||||
|
||||
auto buffer = GCAllocator.instance.allocate(1024 * 1024 * 4);
|
||||
// deallocate upon scope's end (alternatively: leave it to collection)
|
||||
scope(exit) GCAllocator.instance.deallocate(buffer);
|
||||
//...
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
@nogc @system nothrow unittest
|
||||
{
|
||||
import std.experimental.allocator.mallocator;
|
||||
|
||||
auto buffer = Mallocator.instance.allocate(1024 * 1024 * 4);
|
||||
scope(exit) Mallocator.instance.deallocate(buffer);
|
||||
//...
|
||||
}
|
||||
|
||||
pure @nogc @system nothrow unittest
|
||||
{
|
||||
import std.experimental.allocator.mallocator;
|
||||
|
||||
auto buffer = AlignedMallocator.instance.alignedAllocate(1024 * 1024 * 4,
|
||||
128);
|
||||
scope(exit) AlignedMallocator.instance.deallocate(buffer);
|
||||
//...
|
||||
}
|
||||
|
|
@ -0,0 +1,263 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
// Install a new allocator that is faster for 128-byte allocations.
|
||||
import std.experimental.allocator.building_blocks.free_list : FreeList;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
auto oldAllocator = theAllocator;
|
||||
scope(exit) theAllocator = oldAllocator;
|
||||
theAllocator = allocatorObject(FreeList!(GCAllocator, 128)());
|
||||
// Use the now changed allocator to allocate an array
|
||||
const ubyte[] arr = theAllocator.makeArray!ubyte(128);
|
||||
assert(arr.ptr);
|
||||
//...
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
// Dynamically allocate one integer
|
||||
const int* p1 = theAllocator.make!int;
|
||||
// It's implicitly initialized with its .init value
|
||||
assert(*p1 == 0);
|
||||
// Dynamically allocate one double, initialize to 42.5
|
||||
const double* p2 = theAllocator.make!double(42.5);
|
||||
assert(*p2 == 42.5);
|
||||
|
||||
// Dynamically allocate a struct
|
||||
static struct Point
|
||||
{
|
||||
int x, y, z;
|
||||
}
|
||||
// Use the generated constructor taking field values in order
|
||||
const Point* p = theAllocator.make!Point(1, 2);
|
||||
assert(p.x == 1 && p.y == 2 && p.z == 0);
|
||||
|
||||
// Dynamically allocate a class object
|
||||
static class Customer
|
||||
{
|
||||
uint id = uint.max;
|
||||
this() {}
|
||||
this(uint id) { this.id = id; }
|
||||
// ...
|
||||
}
|
||||
Customer cust = theAllocator.make!Customer;
|
||||
assert(cust.id == uint.max); // default initialized
|
||||
cust = theAllocator.make!Customer(42);
|
||||
assert(cust.id == 42);
|
||||
|
||||
// explicit passing of outer pointer
|
||||
static class Outer
|
||||
{
|
||||
int x = 3;
|
||||
class Inner
|
||||
{
|
||||
auto getX() { return x; }
|
||||
}
|
||||
}
|
||||
auto outer = theAllocator.make!Outer();
|
||||
auto inner = theAllocator.make!(Outer.Inner)(outer);
|
||||
assert(outer.x == inner.getX);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
static void test(T)()
|
||||
{
|
||||
T[] a = theAllocator.makeArray!T(2);
|
||||
assert(a.equal([0, 0]));
|
||||
a = theAllocator.makeArray!T(3, 42);
|
||||
assert(a.equal([42, 42, 42]));
|
||||
import std.range : only;
|
||||
a = theAllocator.makeArray!T(only(42, 43, 44));
|
||||
assert(a.equal([42, 43, 44]));
|
||||
}
|
||||
test!int();
|
||||
test!(shared int)();
|
||||
test!(const int)();
|
||||
test!(immutable int)();
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
auto arr = theAllocator.makeArray!int([1, 2, 3]);
|
||||
assert(theAllocator.expandArray(arr, 2));
|
||||
assert(arr == [1, 2, 3, 0, 0]);
|
||||
import std.range : only;
|
||||
assert(theAllocator.expandArray(arr, only(4, 5)));
|
||||
assert(arr == [1, 2, 3, 0, 0, 4, 5]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
int[] a = theAllocator.makeArray!int(100, 42);
|
||||
assert(a.length == 100);
|
||||
assert(theAllocator.shrinkArray(a, 98));
|
||||
assert(a.length == 2);
|
||||
assert(a == [42, 42]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
|
||||
auto mArray = Mallocator.instance.makeMultidimensionalArray!int(2, 3, 6);
|
||||
|
||||
// deallocate when exiting scope
|
||||
scope(exit)
|
||||
{
|
||||
Mallocator.instance.disposeMultidimensionalArray(mArray);
|
||||
}
|
||||
|
||||
assert(mArray.length == 2);
|
||||
foreach (lvl2Array; mArray)
|
||||
{
|
||||
assert(lvl2Array.length == 3);
|
||||
foreach (lvl3Array; lvl2Array)
|
||||
assert(lvl3Array.length == 6);
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
struct TestAllocator
|
||||
{
|
||||
import std.experimental.allocator.common : platformAlignment;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
|
||||
alias allocator = Mallocator.instance;
|
||||
|
||||
private static struct ByteRange
|
||||
{
|
||||
void* ptr;
|
||||
size_t length;
|
||||
}
|
||||
|
||||
private ByteRange[] _allocations;
|
||||
|
||||
enum uint alignment = platformAlignment;
|
||||
|
||||
void[] allocate(size_t numBytes)
|
||||
{
|
||||
auto ret = allocator.allocate(numBytes);
|
||||
_allocations ~= ByteRange(ret.ptr, ret.length);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool deallocate(void[] bytes)
|
||||
{
|
||||
import std.algorithm.mutation : remove;
|
||||
import std.algorithm.searching : canFind;
|
||||
|
||||
bool pred(ByteRange other)
|
||||
{ return other.ptr == bytes.ptr && other.length == bytes.length; }
|
||||
|
||||
assert(_allocations.canFind!pred);
|
||||
|
||||
_allocations = _allocations.remove!pred;
|
||||
return allocator.deallocate(bytes);
|
||||
}
|
||||
|
||||
~this()
|
||||
{
|
||||
assert(!_allocations.length);
|
||||
}
|
||||
}
|
||||
|
||||
TestAllocator allocator;
|
||||
|
||||
auto mArray = allocator.makeMultidimensionalArray!int(2, 3, 5, 6, 7, 2);
|
||||
|
||||
allocator.disposeMultidimensionalArray(mArray);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
|
||||
RCIAllocator a = allocatorObject(Mallocator.instance);
|
||||
auto b = a.allocate(100);
|
||||
assert(b.length == 100);
|
||||
assert(a.deallocate(b));
|
||||
|
||||
// The in-situ region must be used by pointer
|
||||
import std.experimental.allocator.building_blocks.region : InSituRegion;
|
||||
auto r = InSituRegion!1024();
|
||||
a = allocatorObject(&r);
|
||||
b = a.allocate(200);
|
||||
assert(b.length == 200);
|
||||
// In-situ regions can deallocate the last allocation
|
||||
assert(a.deallocate(b));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
import std.experimental.allocator.building_blocks.free_list : FreeList;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
|
||||
static assert(!is(ThreadLocal!Mallocator));
|
||||
static assert(!is(ThreadLocal!GCAllocator));
|
||||
alias Allocator = ThreadLocal!(FreeList!(GCAllocator, 0, 8));
|
||||
auto b = Allocator.instance.allocate(5);
|
||||
static assert(__traits(hasMember, Allocator, "allocate"));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator;
|
||||
|
||||
import std.experimental.allocator.building_blocks.allocator_list : AllocatorList;
|
||||
import std.experimental.allocator.building_blocks.bitmapped_block : BitmappedBlock;
|
||||
import std.experimental.allocator.building_blocks.segregator : Segregator;
|
||||
import std.experimental.allocator.building_blocks.bucketizer : Bucketizer;
|
||||
import std.experimental.allocator.building_blocks.free_list : FreeList;
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
|
||||
/// Define an allocator bound to the built-in GC.
|
||||
auto alloc = allocatorObject(GCAllocator.instance);
|
||||
auto b = alloc.allocate(42);
|
||||
assert(b.length == 42);
|
||||
assert(alloc.deallocate(b));
|
||||
|
||||
import std.algorithm.comparison : max;
|
||||
// Define an elaborate allocator and bind it to the class API.
|
||||
alias FList = FreeList!(GCAllocator, 0, unbounded);
|
||||
alias A = ThreadLocal!(
|
||||
Segregator!(
|
||||
8, FreeList!(GCAllocator, 0, 8),
|
||||
128, Bucketizer!(FList, 1, 128, 16),
|
||||
256, Bucketizer!(FList, 129, 256, 32),
|
||||
512, Bucketizer!(FList, 257, 512, 64),
|
||||
1024, Bucketizer!(FList, 513, 1024, 128),
|
||||
2048, Bucketizer!(FList, 1025, 2048, 256),
|
||||
3584, Bucketizer!(FList, 2049, 3584, 512),
|
||||
4072 * 1024, AllocatorList!(
|
||||
(n) => BitmappedBlock!(4096)(cast(ubyte[]) GCAllocator.instance.allocate(
|
||||
max(n, 4072 * 1024)))),
|
||||
GCAllocator
|
||||
)
|
||||
);
|
||||
|
||||
auto alloc2 = allocatorObject(A.instance);
|
||||
b = alloc2.allocate(101);
|
||||
assert(alloc2.deallocate(b));
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.showcase;
|
||||
|
||||
StackFront!4096 a;
|
||||
auto b = a.allocate(4000);
|
||||
assert(b.length == 4000);
|
||||
auto c = a.allocate(4000);
|
||||
assert(c.length == 4000);
|
||||
a.deallocate(b);
|
||||
a.deallocate(c);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.showcase;
|
||||
|
||||
auto alloc = mmapRegionList(1024 * 1024);
|
||||
const b = alloc.allocate(100);
|
||||
assert(b.length == 100);
|
||||
}
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.experimental.allocator.typed;
|
||||
|
||||
import std.experimental.allocator.gc_allocator : GCAllocator;
|
||||
import std.experimental.allocator.mallocator : Mallocator;
|
||||
import std.experimental.allocator.mmap_allocator : MmapAllocator;
|
||||
alias MyAllocator = TypedAllocator!(GCAllocator,
|
||||
AllocFlag.fixedSize | AllocFlag.threadLocal, Mallocator,
|
||||
AllocFlag.fixedSize | AllocFlag.threadLocal
|
||||
| AllocFlag.hasNoIndirections,
|
||||
MmapAllocator,
|
||||
);
|
||||
|
||||
MyAllocator a;
|
||||
auto b = &a.allocatorFor!0();
|
||||
static assert(is(typeof(*b) == shared const(GCAllocator)));
|
||||
enum f1 = AllocFlag.fixedSize | AllocFlag.threadLocal;
|
||||
auto c = &a.allocatorFor!f1();
|
||||
static assert(is(typeof(*c) == Mallocator));
|
||||
enum f2 = AllocFlag.fixedSize | AllocFlag.threadLocal;
|
||||
static assert(is(typeof(a.allocatorFor!f2()) == Mallocator));
|
||||
// Partial match
|
||||
enum f3 = AllocFlag.threadLocal;
|
||||
static assert(is(typeof(a.allocatorFor!f3()) == Mallocator));
|
||||
|
||||
int* p = a.make!int;
|
||||
scope(exit) a.dispose(p);
|
||||
int[] arr = a.makeArray!int(42);
|
||||
scope(exit) a.dispose(arr);
|
||||
assert(a.expandArray(arr, 3));
|
||||
assert(a.shrinkArray(arr, 4));
|
||||
}
|
||||
|
756
libphobos/testsuite/libphobos.phobos/std_file.d
Normal file
756
libphobos/testsuite/libphobos.phobos/std_file.d
Normal file
|
@ -0,0 +1,756 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
assertThrown!FileException("non.existing.file.".readText);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.utf : byChar;
|
||||
scope(exit)
|
||||
{
|
||||
assert(exists(deleteme));
|
||||
remove(deleteme);
|
||||
}
|
||||
|
||||
std.file.write(deleteme, "1234"); // deleteme is the name of a temporary file
|
||||
assert(read(deleteme, 2) == "12");
|
||||
assert(read(deleteme.byChar) == "1234");
|
||||
assert((cast(const(ubyte)[])read(deleteme)).length == 4);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
write(deleteme, "abc"); // deleteme is the name of a temporary file
|
||||
scope(exit) remove(deleteme);
|
||||
string content = readText(deleteme);
|
||||
assert(content == "abc");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
scope(exit)
|
||||
{
|
||||
assert(exists(deleteme));
|
||||
remove(deleteme);
|
||||
}
|
||||
|
||||
int[] a = [ 0, 1, 1, 2, 3, 5, 8 ];
|
||||
write(deleteme, a); // deleteme is the name of a temporary file
|
||||
const bytes = read(deleteme);
|
||||
const fileInts = () @trusted { return cast(int[]) bytes; }();
|
||||
assert(fileInts == a);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
scope(exit)
|
||||
{
|
||||
assert(exists(deleteme));
|
||||
remove(deleteme);
|
||||
}
|
||||
|
||||
int[] a = [ 0, 1, 1, 2, 3, 5, 8 ];
|
||||
write(deleteme, a); // deleteme is the name of a temporary file
|
||||
int[] b = [ 13, 21 ];
|
||||
append(deleteme, b);
|
||||
const bytes = read(deleteme);
|
||||
const fileInts = () @trusted { return cast(int[]) bytes; }();
|
||||
assert(fileInts == a ~ b);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
auto t1 = deleteme, t2 = deleteme~"2";
|
||||
scope(exit) foreach (t; [t1, t2]) if (t.exists) t.remove();
|
||||
|
||||
t1.write("1");
|
||||
t1.rename(t2);
|
||||
assert(t2.readText == "1");
|
||||
|
||||
t1.write("2");
|
||||
t1.rename(t2);
|
||||
assert(t2.readText == "2");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
deleteme.write("Hello");
|
||||
assert(deleteme.readText == "Hello");
|
||||
|
||||
deleteme.remove;
|
||||
assertThrown!FileException(deleteme.readText);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
scope(exit) deleteme.remove;
|
||||
|
||||
// create a file of size 1
|
||||
write(deleteme, "a");
|
||||
assert(getSize(deleteme) == 1);
|
||||
|
||||
// create a file of size 3
|
||||
write(deleteme, "abc");
|
||||
assert(getSize(deleteme) == 3);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.datetime : abs, SysTime;
|
||||
|
||||
scope(exit) deleteme.remove;
|
||||
write(deleteme, "a");
|
||||
|
||||
SysTime accessTime, modificationTime;
|
||||
|
||||
getTimes(deleteme, accessTime, modificationTime);
|
||||
|
||||
import std.datetime : Clock, seconds;
|
||||
auto currTime = Clock.currTime();
|
||||
enum leeway = 5.seconds;
|
||||
|
||||
auto diffAccess = accessTime - currTime;
|
||||
auto diffModification = modificationTime - currTime;
|
||||
assert(abs(diffAccess) <= leeway);
|
||||
assert(abs(diffModification) <= leeway);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.datetime : DateTime, hnsecs, SysTime;
|
||||
|
||||
scope(exit) deleteme.remove;
|
||||
write(deleteme, "a");
|
||||
|
||||
SysTime accessTime = SysTime(DateTime(2010, 10, 4, 0, 0, 30));
|
||||
SysTime modificationTime = SysTime(DateTime(2018, 10, 4, 0, 0, 30));
|
||||
setTimes(deleteme, accessTime, modificationTime);
|
||||
|
||||
SysTime accessTimeResolved, modificationTimeResolved;
|
||||
getTimes(deleteme, accessTimeResolved, modificationTimeResolved);
|
||||
|
||||
assert(accessTime == accessTimeResolved);
|
||||
assert(modificationTime == modificationTimeResolved);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.datetime : abs, DateTime, hnsecs, SysTime;
|
||||
scope(exit) deleteme.remove;
|
||||
|
||||
import std.datetime : Clock, seconds;
|
||||
auto currTime = Clock.currTime();
|
||||
enum leeway = 5.seconds;
|
||||
deleteme.write("bb");
|
||||
assert(abs(deleteme.timeLastModified - currTime) <= leeway);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.datetime : SysTime;
|
||||
|
||||
assert("file.does.not.exist".timeLastModified(SysTime.min) == SysTime.min);
|
||||
|
||||
auto source = deleteme ~ "source";
|
||||
auto target = deleteme ~ "target";
|
||||
scope(exit) source.remove, target.remove;
|
||||
|
||||
source.write(".");
|
||||
assert(target.timeLastModified(SysTime.min) < source.timeLastModified);
|
||||
target.write(".");
|
||||
assert(target.timeLastModified(SysTime.min) >= source.timeLastModified);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
auto f = deleteme ~ "does.not.exist";
|
||||
assert(!f.exists);
|
||||
|
||||
f.write("hello");
|
||||
assert(f.exists);
|
||||
|
||||
f.remove;
|
||||
assert(!f.exists);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
assert(".".exists);
|
||||
assert(!"this file does not exist".exists);
|
||||
deleteme.write("a\n");
|
||||
scope(exit) deleteme.remove;
|
||||
assert(deleteme.exists);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto f = deleteme ~ "file";
|
||||
scope(exit) f.remove;
|
||||
|
||||
assert(!f.exists);
|
||||
assertThrown!FileException(f.getAttributes);
|
||||
|
||||
f.write(".");
|
||||
auto attributes = f.getAttributes;
|
||||
assert(!attributes.attrIsDir);
|
||||
assert(attributes.attrIsFile);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
scope(exit) dir.rmdir;
|
||||
|
||||
assert(!dir.exists);
|
||||
assertThrown!FileException(dir.getAttributes);
|
||||
|
||||
dir.mkdir;
|
||||
auto attributes = dir.getAttributes;
|
||||
assert(attributes.attrIsDir);
|
||||
assert(!attributes.attrIsFile);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto source = deleteme ~ "source";
|
||||
auto target = deleteme ~ "target";
|
||||
|
||||
assert(!source.exists);
|
||||
assertThrown!FileException(source.getLinkAttributes);
|
||||
|
||||
// symlinking isn't available on Windows
|
||||
version (Posix)
|
||||
{
|
||||
scope(exit) source.remove, target.remove;
|
||||
|
||||
target.write("target");
|
||||
target.symlink(source);
|
||||
assert(source.readText == "target");
|
||||
assert(source.isSymlink);
|
||||
assert(source.getLinkAttributes.attrIsSymlink);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto f = deleteme ~ "file";
|
||||
scope(exit) f.remove;
|
||||
|
||||
assert(!f.exists);
|
||||
assertThrown!FileException(f.getLinkAttributes);
|
||||
|
||||
f.write(".");
|
||||
auto attributes = f.getLinkAttributes;
|
||||
assert(!attributes.attrIsDir);
|
||||
assert(attributes.attrIsFile);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
scope(exit) dir.rmdir;
|
||||
|
||||
assert(!dir.exists);
|
||||
assertThrown!FileException(dir.getLinkAttributes);
|
||||
|
||||
dir.mkdir;
|
||||
auto attributes = dir.getLinkAttributes;
|
||||
assert(attributes.attrIsDir);
|
||||
assert(!attributes.attrIsFile);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
import std.conv : octal;
|
||||
|
||||
auto f = deleteme ~ "file";
|
||||
version (Posix)
|
||||
{
|
||||
scope(exit) f.remove;
|
||||
|
||||
assert(!f.exists);
|
||||
assertThrown!FileException(f.setAttributes(octal!777));
|
||||
|
||||
f.write(".");
|
||||
auto attributes = f.getAttributes;
|
||||
assert(!attributes.attrIsDir);
|
||||
assert(attributes.attrIsFile);
|
||||
|
||||
f.setAttributes(octal!777);
|
||||
attributes = f.getAttributes;
|
||||
|
||||
assert((attributes & 1023) == octal!777);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
import std.conv : octal;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
version (Posix)
|
||||
{
|
||||
scope(exit) dir.rmdir;
|
||||
|
||||
assert(!dir.exists);
|
||||
assertThrown!FileException(dir.setAttributes(octal!777));
|
||||
|
||||
dir.mkdir;
|
||||
auto attributes = dir.getAttributes;
|
||||
assert(attributes.attrIsDir);
|
||||
assert(!attributes.attrIsFile);
|
||||
|
||||
dir.setAttributes(octal!777);
|
||||
attributes = dir.getAttributes;
|
||||
|
||||
assert((attributes & 1023) == octal!777);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
auto f = deleteme ~ "f";
|
||||
scope(exit) dir.rmdir, f.remove;
|
||||
|
||||
assert(!dir.exists);
|
||||
assertThrown!FileException(dir.isDir);
|
||||
|
||||
dir.mkdir;
|
||||
assert(dir.isDir);
|
||||
|
||||
f.write(".");
|
||||
assert(!f.isDir);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
auto f = deleteme ~ "f";
|
||||
scope(exit) dir.rmdir, f.remove;
|
||||
|
||||
assert(!dir.exists);
|
||||
assertThrown!FileException(dir.getAttributes.attrIsDir);
|
||||
|
||||
dir.mkdir;
|
||||
assert(dir.isDir);
|
||||
assert(dir.getAttributes.attrIsDir);
|
||||
|
||||
f.write(".");
|
||||
assert(!f.isDir);
|
||||
assert(!f.getAttributes.attrIsDir);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
auto f = deleteme ~ "f";
|
||||
scope(exit) dir.rmdir, f.remove;
|
||||
|
||||
dir.mkdir;
|
||||
assert(!dir.isFile);
|
||||
|
||||
assert(!f.exists);
|
||||
assertThrown!FileException(f.isFile);
|
||||
|
||||
f.write(".");
|
||||
assert(f.isFile);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
auto f = deleteme ~ "f";
|
||||
scope(exit) dir.rmdir, f.remove;
|
||||
|
||||
dir.mkdir;
|
||||
assert(!dir.isFile);
|
||||
assert(!dir.getAttributes.attrIsFile);
|
||||
|
||||
assert(!f.exists);
|
||||
assertThrown!FileException(f.getAttributes.attrIsFile);
|
||||
|
||||
f.write(".");
|
||||
assert(f.isFile);
|
||||
assert(f.getAttributes.attrIsFile);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto source = deleteme ~ "source";
|
||||
auto target = deleteme ~ "target";
|
||||
|
||||
assert(!source.exists);
|
||||
assertThrown!FileException(source.isSymlink);
|
||||
|
||||
// symlinking isn't available on Windows
|
||||
version (Posix)
|
||||
{
|
||||
scope(exit) source.remove, target.remove;
|
||||
|
||||
target.write("target");
|
||||
target.symlink(source);
|
||||
assert(source.readText == "target");
|
||||
assert(source.isSymlink);
|
||||
assert(source.getLinkAttributes.attrIsSymlink);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto source = deleteme ~ "source";
|
||||
auto target = deleteme ~ "target";
|
||||
|
||||
assert(!source.exists);
|
||||
assertThrown!FileException(source.getLinkAttributes.attrIsSymlink);
|
||||
|
||||
// symlinking isn't available on Windows
|
||||
version (Posix)
|
||||
{
|
||||
scope(exit) source.remove, target.remove;
|
||||
|
||||
target.write("target");
|
||||
target.symlink(source);
|
||||
assert(source.readText == "target");
|
||||
assert(source.isSymlink);
|
||||
assert(source.getLinkAttributes.attrIsSymlink);
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.sorting : sort;
|
||||
import std.array : array;
|
||||
import std.path : buildPath;
|
||||
|
||||
auto cwd = getcwd;
|
||||
auto dir = deleteme ~ "dir";
|
||||
dir.mkdir;
|
||||
scope(exit) cwd.chdir, dir.rmdirRecurse;
|
||||
|
||||
dir.buildPath("a").write(".");
|
||||
dir.chdir; // step into dir
|
||||
"b".write(".");
|
||||
assert(dirEntries(".", SpanMode.shallow).array.sort.equal(
|
||||
[".".buildPath("a"), ".".buildPath("b")]
|
||||
));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.file : mkdir;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
scope(exit) dir.rmdir;
|
||||
|
||||
dir.mkdir;
|
||||
assert(dir.exists);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
assertThrown("a/b/c/d/e".mkdir);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.path : buildPath;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
scope(exit) dir.rmdirRecurse;
|
||||
|
||||
dir.mkdir;
|
||||
assert(dir.exists);
|
||||
dir.mkdirRecurse; // does nothing
|
||||
|
||||
// creates all parent directories as needed
|
||||
auto nested = dir.buildPath("a", "b", "c");
|
||||
nested.mkdirRecurse;
|
||||
assert(nested.exists);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
scope(exit) deleteme.remove;
|
||||
deleteme.write("a");
|
||||
|
||||
// cannot make directory as it's already a file
|
||||
assertThrown!FileException(deleteme.mkdirRecurse);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
auto dir = deleteme ~ "dir";
|
||||
|
||||
dir.mkdir;
|
||||
assert(dir.exists);
|
||||
dir.rmdir;
|
||||
assert(!dir.exists);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
auto s = getcwd();
|
||||
assert(s.length);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.path : isAbsolute;
|
||||
auto path = thisExePath();
|
||||
|
||||
assert(path.exists);
|
||||
assert(path.isAbsolute);
|
||||
assert(path.isFile);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
auto source = deleteme ~ "source";
|
||||
auto target = deleteme ~ "target";
|
||||
auto targetNonExistent = deleteme ~ "target2";
|
||||
|
||||
scope(exit) source.remove, target.remove, targetNonExistent.remove;
|
||||
|
||||
source.write("source");
|
||||
target.write("target");
|
||||
|
||||
assert(target.readText == "target");
|
||||
|
||||
source.copy(target);
|
||||
assert(target.readText == "source");
|
||||
|
||||
source.copy(targetNonExistent);
|
||||
assert(targetNonExistent.readText == "source");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.path : buildPath;
|
||||
|
||||
auto dir = deleteme.buildPath("a", "b", "c");
|
||||
|
||||
dir.mkdirRecurse;
|
||||
assert(dir.exists);
|
||||
|
||||
deleteme.rmdirRecurse;
|
||||
assert(!dir.exists);
|
||||
assert(!deleteme.exists);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.iteration : map;
|
||||
import std.algorithm.sorting : sort;
|
||||
import std.array : array;
|
||||
import std.path : buildPath, relativePath;
|
||||
|
||||
auto root = deleteme ~ "root";
|
||||
scope(exit) root.rmdirRecurse;
|
||||
root.mkdir;
|
||||
|
||||
root.buildPath("animals").mkdir;
|
||||
root.buildPath("animals", "cat").mkdir;
|
||||
|
||||
alias removeRoot = (return scope e) => e.relativePath(root);
|
||||
|
||||
assert(root.dirEntries(SpanMode.depth).map!removeRoot.equal(
|
||||
[buildPath("animals", "cat"), "animals"]));
|
||||
|
||||
assert(root.dirEntries(SpanMode.breadth).map!removeRoot.equal(
|
||||
["animals", buildPath("animals", "cat")]));
|
||||
|
||||
root.buildPath("plants").mkdir;
|
||||
|
||||
assert(root.dirEntries(SpanMode.shallow).array.sort.map!removeRoot.equal(
|
||||
["animals", "plants"]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
string[] listdir(string pathname)
|
||||
{
|
||||
import std.algorithm.iteration : map, filter;
|
||||
import std.array : array;
|
||||
import std.path : baseName;
|
||||
|
||||
return dirEntries(pathname, SpanMode.shallow)
|
||||
.filter!(a => a.isFile)
|
||||
.map!((return a) => baseName(a.name))
|
||||
.array;
|
||||
}
|
||||
|
||||
// Can be safe only with -preview=dip1000
|
||||
@safe void main(string[] args)
|
||||
{
|
||||
import std.stdio : writefln;
|
||||
|
||||
string[] files = listdir(args[1]);
|
||||
writefln("%s", files);
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.typecons : tuple;
|
||||
|
||||
scope(exit)
|
||||
{
|
||||
assert(exists(deleteme));
|
||||
remove(deleteme);
|
||||
}
|
||||
|
||||
write(deleteme, "12 12.25\n345 1.125"); // deleteme is the name of a temporary file
|
||||
|
||||
// Load file; each line is an int followed by comma, whitespace and a
|
||||
// double.
|
||||
auto a = slurp!(int, double)(deleteme, "%s %s");
|
||||
assert(a.length == 2);
|
||||
assert(a[0] == tuple(12, 12.25));
|
||||
assert(a[1] == tuple(345, 1.125));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.ascii : letters;
|
||||
import std.conv : to;
|
||||
import std.path : buildPath;
|
||||
import std.random : randomSample;
|
||||
import std.utf : byCodeUnit;
|
||||
|
||||
// random id with 20 letters
|
||||
auto id = letters.byCodeUnit.randomSample(20).to!string;
|
||||
auto myFile = tempDir.buildPath(id ~ "my_tmp_file");
|
||||
scope(exit) myFile.remove;
|
||||
|
||||
myFile.write("hello");
|
||||
assert(myFile.readText == "hello");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.file;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
auto space = getAvailableDiskSpace(".");
|
||||
assert(space > 0);
|
||||
|
||||
assertThrown!FileException(getAvailableDiskSpace("ThisFileDoesNotExist123123"));
|
||||
}
|
||||
|
139
libphobos/testsuite/libphobos.phobos/std_format_package.d
Normal file
139
libphobos/testsuite/libphobos.phobos/std_format_package.d
Normal file
|
@ -0,0 +1,139 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.format;
|
||||
|
||||
// Easiest way is to use `%s` everywhere:
|
||||
assert(format("I got %s %s for %s euros.", 30, "eggs", 5.27) == "I got 30 eggs for 5.27 euros.");
|
||||
|
||||
// Other format characters provide more control:
|
||||
assert(format("I got %b %(%X%) for %f euros.", 30, "eggs", 5.27) == "I got 11110 65676773 for 5.270000 euros.");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.format;
|
||||
|
||||
/*
|
||||
The trailing end of the sub-format string following the specifier for
|
||||
each item is interpreted as the array delimiter, and is therefore
|
||||
omitted following the last array item:
|
||||
*/
|
||||
assert(format("My items are %(%s %).", [1,2,3]) == "My items are 1 2 3.");
|
||||
assert(format("My items are %(%s, %).", [1,2,3]) == "My items are 1, 2, 3.");
|
||||
|
||||
/*
|
||||
The "%|" delimiter specifier may be used to indicate where the
|
||||
delimiter begins, so that the portion of the format string prior to
|
||||
it will be retained in the last array element:
|
||||
*/
|
||||
assert(format("My items are %(-%s-%|, %).", [1,2,3]) == "My items are -1-, -2-, -3-.");
|
||||
|
||||
/*
|
||||
These compound format specifiers may be nested in the case of a
|
||||
nested array argument:
|
||||
*/
|
||||
auto mat = [[1, 2, 3],
|
||||
[4, 5, 6],
|
||||
[7, 8, 9]];
|
||||
|
||||
assert(format("%(%(%d %) - %)", mat), "1 2 3 - 4 5 6 - 7 8 9");
|
||||
assert(format("[%(%(%d %) - %)]", mat), "[1 2 3 - 4 5 6 - 7 8 9]");
|
||||
assert(format("[%([%(%d %)]%| - %)]", mat), "[1 2 3] - [4 5 6] - [7 8 9]");
|
||||
|
||||
/*
|
||||
Strings and characters are escaped automatically inside compound
|
||||
format specifiers. To avoid this behavior, use "%-(" instead of "%(":
|
||||
*/
|
||||
assert(format("My friends are %s.", ["John", "Nancy"]) == `My friends are ["John", "Nancy"].`);
|
||||
assert(format("My friends are %(%s, %).", ["John", "Nancy"]) == `My friends are "John", "Nancy".`);
|
||||
assert(format("My friends are %-(%s, %).", ["John", "Nancy"]) == `My friends are John, Nancy.`);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.format;
|
||||
|
||||
// Flags can be used to influence to outcome:
|
||||
assert(format("%g != %+#g", 3.14, 3.14) == "3.14 != +3.14000");
|
||||
|
||||
// Width and precision help to arrange the formatted result:
|
||||
assert(format(">%10.2f<", 1234.56789) == "> 1234.57<");
|
||||
|
||||
// Numbers can be grouped:
|
||||
assert(format("%,4d", int.max) == "21,4748,3647");
|
||||
|
||||
// It's possible to specify the position of an argument:
|
||||
assert(format("%3$s %1$s", 3, 17, 5) == "5 3");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.format;
|
||||
|
||||
// Width as argument
|
||||
assert(format(">%*s<", 10, "abc") == "> abc<");
|
||||
|
||||
// Precision as argument
|
||||
assert(format(">%.*f<", 5, 123.2) == ">123.20000<");
|
||||
|
||||
// Grouping as argument
|
||||
assert(format("%,*d", 1, int.max) == "2,1,4,7,4,8,3,6,4,7");
|
||||
|
||||
// Grouping separator as argument
|
||||
assert(format("%,3?d", '_', int.max) == "2_147_483_647");
|
||||
|
||||
// All at once
|
||||
assert(format("%*.*,*?d", 20, 15, 6, '/', int.max) == " 000/002147/483647");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.format;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
|
||||
assertThrown!FormatException(format("%d", "foo"));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format;
|
||||
|
||||
assert(format("Here are %d %s.", 3, "apples") == "Here are 3 apples.");
|
||||
|
||||
assert("Increase: %7.2f %%".format(17.4285) == "Increase: 17.43 %");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format;
|
||||
|
||||
auto s = format!"%s is %s"("Pi", 3.14);
|
||||
assert(s == "Pi is 3.14");
|
||||
|
||||
// This line doesn't compile, because 3.14 cannot be formatted with %d:
|
||||
// s = format!"%s is %d"("Pi", 3.14);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format;
|
||||
|
||||
char[20] buf;
|
||||
assert(sformat(buf[], "Here are %d %s.", 3, "apples") == "Here are 3 apples.");
|
||||
|
||||
assert(buf[].sformat("Increase: %7.2f %%", 17.4285) == "Increase: 17.43 %");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format;
|
||||
|
||||
char[20] buf;
|
||||
|
||||
assert(sformat!"Here are %d %s."(buf[], 3, "apples") == "Here are 3 apples.");
|
||||
|
||||
// This line doesn't compile, because 3.14 cannot be formatted with %d:
|
||||
// writeln(sformat!"Here are %d %s."(buf[], 3.14, "apples"));
|
||||
}
|
||||
|
275
libphobos/testsuite/libphobos.phobos/std_format_read.d
Normal file
275
libphobos/testsuite/libphobos.phobos/std_format_read.d
Normal file
|
@ -0,0 +1,275 @@
|
|||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto str = "false";
|
||||
auto spec = singleSpec("%s");
|
||||
assert(str.unformatValue!bool(spec) == false);
|
||||
|
||||
str = "1";
|
||||
spec = singleSpec("%d");
|
||||
assert(str.unformatValue!bool(spec) == true);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto str = "null";
|
||||
auto spec = singleSpec("%s");
|
||||
assert(str.unformatValue!(typeof(null))(spec) == null);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
// signed decimal values
|
||||
auto str = "123";
|
||||
auto spec = singleSpec("%s");
|
||||
assert(str.unformatValue!int(spec) == 123);
|
||||
|
||||
// hexadecimal values
|
||||
str = "ABC";
|
||||
spec = singleSpec("%X");
|
||||
assert(str.unformatValue!int(spec) == 2748);
|
||||
|
||||
// octal values
|
||||
str = "11610";
|
||||
spec = singleSpec("%o");
|
||||
assert(str.unformatValue!int(spec) == 5000);
|
||||
|
||||
// raw read, depends on endianess
|
||||
str = "\x75\x01";
|
||||
spec = singleSpec("%r");
|
||||
auto result = str.unformatValue!short(spec);
|
||||
assert(result == 373 /* little endian */ || result == 29953 /* big endian */ );
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format.spec : singleSpec;
|
||||
import std.math.operations : isClose;
|
||||
|
||||
// natural notation
|
||||
auto str = "123.456";
|
||||
auto spec = singleSpec("%s");
|
||||
assert(str.unformatValue!double(spec).isClose(123.456));
|
||||
|
||||
// scientific notation
|
||||
str = "1e17";
|
||||
spec = singleSpec("%e");
|
||||
assert(str.unformatValue!double(spec).isClose(1e17));
|
||||
|
||||
// raw read, depends on endianess
|
||||
str = "\x40\x00\x00\xBF";
|
||||
spec = singleSpec("%r");
|
||||
auto result = str.unformatValue!float(spec);
|
||||
assert(isClose(result, -0.5) /* little endian */ || isClose(result, 2.0) /* big endian */ );
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
// only the first character is read
|
||||
auto str = "abc";
|
||||
auto spec = singleSpec("%s");
|
||||
assert(str.unformatValue!char(spec) == 'a');
|
||||
|
||||
// using a numerical format character treats the read number as unicode code point
|
||||
str = "65";
|
||||
spec = singleSpec("%d");
|
||||
assert(str.unformatValue!char(spec) == 'A');
|
||||
|
||||
str = "41";
|
||||
spec = singleSpec("%x");
|
||||
assert(str.unformatValue!char(spec) == 'A');
|
||||
|
||||
str = "10003";
|
||||
spec = singleSpec("%d");
|
||||
assert(str.unformatValue!dchar(spec) == '✓');
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
// string value
|
||||
string str = "aaa";
|
||||
auto spec = singleSpec("%s");
|
||||
assert(str.unformatValue!(dchar[])(spec) == "aaa"d);
|
||||
|
||||
// fixed size array with characters
|
||||
str = "aaa";
|
||||
spec = singleSpec("%s");
|
||||
dchar[3] ret = ['a', 'a', 'a'];
|
||||
assert(str.unformatValue!(dchar[3])(spec) == ret);
|
||||
|
||||
// dynamic array
|
||||
str = "[1, 2, 3, 4]";
|
||||
spec = singleSpec("%s");
|
||||
assert(str.unformatValue!(int[])(spec) == [1, 2, 3, 4]);
|
||||
|
||||
// fixed size array with integers
|
||||
str = "[1, 2, 3, 4]";
|
||||
spec = singleSpec("%s");
|
||||
int[4] ret2 = [1, 2, 3, 4];
|
||||
assert(str.unformatValue!(int[4])(spec) == ret2);
|
||||
|
||||
// compound specifiers can be used for more control
|
||||
str = "1,2,3";
|
||||
spec = singleSpec("%(%s,%)");
|
||||
assert(str.unformatValue!(int[])(spec) == [1, 2, 3]);
|
||||
|
||||
str = "cool";
|
||||
spec = singleSpec("%(%c%)");
|
||||
assert(str.unformatValue!(char[])(spec) == ['c', 'o', 'o', 'l']);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
// as single value
|
||||
auto str = `["one": 1, "two": 2]`;
|
||||
auto spec = singleSpec("%s");
|
||||
assert(str.unformatValue!(int[string])(spec) == ["one": 1, "two": 2]);
|
||||
|
||||
// with compound specifier for more control
|
||||
str = "1/1, 2/4, 3/9";
|
||||
spec = singleSpec("%(%d/%d%|, %)");
|
||||
assert(str.unformatValue!(int[int])(spec) == [1: 1, 2: 4, 3: 9]);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
string object;
|
||||
char cmp;
|
||||
int value;
|
||||
|
||||
assert(formattedRead("angle < 36", "%s %c %d", object, cmp, value) == 3);
|
||||
assert(object == "angle");
|
||||
assert(cmp == '<');
|
||||
assert(value == 36);
|
||||
|
||||
// reading may end early:
|
||||
assert(formattedRead("length >", "%s %c %d", object, cmp, value) == 2);
|
||||
assert(object == "length");
|
||||
assert(cmp == '>');
|
||||
// value is not changed:
|
||||
assert(value == 36);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
string a;
|
||||
int b;
|
||||
double c;
|
||||
|
||||
assert("hello!124:34.5".formattedRead!"%s!%s:%s"(a, b, c) == 3);
|
||||
assert(a == "hello");
|
||||
assert(b == 124);
|
||||
assert(c == 34.5);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
string item;
|
||||
double amount;
|
||||
|
||||
assert("orange: (12%) 15.25".formattedRead("%s: (%*d%%) %f", item, amount) == 2);
|
||||
assert(item == "orange");
|
||||
assert(amount == 15.25);
|
||||
|
||||
// can also be used with tuples
|
||||
import std.typecons : Tuple;
|
||||
|
||||
Tuple!(int, float) t;
|
||||
char[] line = "1 7643 2.125".dup;
|
||||
formattedRead(line, "%s %*u %s", t);
|
||||
assert(t[0] == 1 && t[1] == 2.125);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
import std.format : FormatException;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto complete = "hello!34.5:124".formattedRead!(string, double, int)("%s!%s:%s");
|
||||
assert(complete == tuple("hello", 34.5, 124));
|
||||
|
||||
// reading ends early
|
||||
assertThrown!FormatException("hello!34.5:".formattedRead!(string, double, int)("%s!%s:%s"));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format : FormatException;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto result = "orange: (12%) 15.25".formattedRead!(string, double)("%s: (%*d%%) %f");
|
||||
assert(result == tuple("orange", 15.25));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
import std.format : FormatException;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto expected = tuple("hello", 124, 34.5);
|
||||
auto result = "hello!124:34.5".formattedRead!("%s!%s:%s", string, int, double);
|
||||
assert(result == expected);
|
||||
|
||||
assertThrown!FormatException("hello!34.5:".formattedRead!("%s!%s:%s", string, double, int));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format : FormatException;
|
||||
import std.typecons : tuple;
|
||||
|
||||
static assert(!__traits(compiles, "orange: (12%) 15.25".formattedRead!("%s: (%*d%%) %f", string, double)));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.read;
|
||||
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
string s = "42";
|
||||
auto spec = singleSpec("%s");
|
||||
assert(unformatValue!int(s, spec) == 42);
|
||||
}
|
||||
|
43
libphobos/testsuite/libphobos.phobos/std_format_spec.d
Normal file
43
libphobos/testsuite/libphobos.phobos/std_format_spec.d
Normal file
|
@ -0,0 +1,43 @@
|
|||
@safe pure unittest
|
||||
{
|
||||
import std.format.spec;
|
||||
|
||||
import std.array : appender;
|
||||
|
||||
auto a = appender!(string)();
|
||||
auto fmt = "Number: %6.4e\nString: %s";
|
||||
auto f = FormatSpec!char(fmt);
|
||||
|
||||
assert(f.writeUpToNextSpec(a));
|
||||
|
||||
assert(a.data == "Number: ");
|
||||
assert(f.trailing == "\nString: %s");
|
||||
assert(f.spec == 'e');
|
||||
assert(f.width == 6);
|
||||
assert(f.precision == 4);
|
||||
|
||||
assert(f.writeUpToNextSpec(a));
|
||||
|
||||
assert(a.data == "Number: \nString: ");
|
||||
assert(f.trailing == "");
|
||||
assert(f.spec == 's');
|
||||
|
||||
assert(!f.writeUpToNextSpec(a));
|
||||
|
||||
assert(a.data == "Number: \nString: ");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.spec;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.write : formatValue;
|
||||
|
||||
auto spec = singleSpec("%10.3e");
|
||||
auto writer = appender!string();
|
||||
writer.formatValue(42.0, spec);
|
||||
|
||||
assert(writer.data == " 4.200e+01");
|
||||
}
|
||||
|
421
libphobos/testsuite/libphobos.phobos/std_format_write.d
Normal file
421
libphobos/testsuite/libphobos.phobos/std_format_write.d
Normal file
|
@ -0,0 +1,421 @@
|
|||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%s");
|
||||
formatValue(w1, true, spec1);
|
||||
|
||||
assert(w1.data == "true");
|
||||
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%#x");
|
||||
formatValue(w2, true, spec2);
|
||||
|
||||
assert(w2.data == "0x1");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w = appender!string();
|
||||
auto spec = singleSpec("%s");
|
||||
formatValue(w, null, spec);
|
||||
|
||||
assert(w.data == "null");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%d");
|
||||
formatValue(w1, -1337, spec1);
|
||||
|
||||
assert(w1.data == "-1337");
|
||||
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%x");
|
||||
formatValue(w2, -1337, spec2);
|
||||
|
||||
assert(w2.data == "fffffac7");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%.3f");
|
||||
formatValue(w1, 1337.7779, spec1);
|
||||
|
||||
assert(w1.data == "1337.778");
|
||||
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%.3e");
|
||||
formatValue(w2, 1337.7779, spec2);
|
||||
|
||||
assert(w2.data == "1.338e+03");
|
||||
|
||||
auto w3 = appender!string();
|
||||
auto spec3 = singleSpec("%.3g");
|
||||
formatValue(w3, 1337.7779, spec3);
|
||||
|
||||
assert(w3.data == "1.34e+03");
|
||||
|
||||
auto w4 = appender!string();
|
||||
auto spec4 = singleSpec("%.3a");
|
||||
formatValue(w4, 1337.7779, spec4);
|
||||
|
||||
assert(w4.data == "0x1.4e7p+10");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%c");
|
||||
formatValue(w1, 'ì', spec1);
|
||||
|
||||
assert(w1.data == "ì");
|
||||
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%#x");
|
||||
formatValue(w2, 'ì', spec2);
|
||||
|
||||
assert(w2.data == "0xec");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%s");
|
||||
formatValue(w1, "hello", spec1);
|
||||
|
||||
assert(w1.data == "hello");
|
||||
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%(%#x%|/%)");
|
||||
formatValue(w2, "hello", spec2);
|
||||
|
||||
assert(w2.data == "0x68/0x65/0x6c/0x6c/0x6f");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w = appender!string();
|
||||
auto spec = singleSpec("%s");
|
||||
int[2] two = [1, 2];
|
||||
formatValue(w, two, spec);
|
||||
|
||||
assert(w.data == "[1, 2]");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%s");
|
||||
auto two = [1, 2];
|
||||
formatValue(w1, two, spec1);
|
||||
|
||||
assert(w1.data == "[1, 2]");
|
||||
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%(%g%|, %)");
|
||||
auto consts = [3.1415926, 299792458, 6.67430e-11];
|
||||
formatValue(w2, consts, spec2);
|
||||
|
||||
assert(w2.data == "3.14159, 2.99792e+08, 6.6743e-11");
|
||||
|
||||
// void[] is treated like ubyte[]
|
||||
auto w3 = appender!string();
|
||||
auto spec3 = singleSpec("%s");
|
||||
void[] val = cast(void[]) cast(ubyte[])[1, 2, 3];
|
||||
formatValue(w3, val, spec3);
|
||||
|
||||
assert(w3.data == "[1, 2, 3]");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto aa = [10:17.5, 20:9.99];
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%s");
|
||||
formatValue(w1, aa, spec1);
|
||||
|
||||
assert(w1.data == "[10:17.5, 20:9.99]" || w1.data == "[20:9.99, 10:17.5]");
|
||||
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%(%x = %.0e%| # %)");
|
||||
formatValue(w2, aa, spec2);
|
||||
|
||||
assert(w2.data == "a = 2e+01 # 14 = 1e+01" || w2.data == "14 = 1e+01 # a = 2e+01");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
enum A { first, second, third }
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%s");
|
||||
formatValue(w1, A.second, spec1);
|
||||
|
||||
assert(w1.data == "second");
|
||||
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%d");
|
||||
formatValue(w2, A.second, spec2);
|
||||
|
||||
assert(w2.data == "1");
|
||||
|
||||
// values of an enum that have no name are formatted with %s using a cast
|
||||
A a = A.third;
|
||||
a++;
|
||||
|
||||
auto w3 = appender!string();
|
||||
auto spec3 = singleSpec("%s");
|
||||
formatValue(w3, a, spec3);
|
||||
|
||||
assert(w3.data == "cast(A)3");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : FormatSpec, singleSpec;
|
||||
|
||||
// Using a `toString` with a writer
|
||||
static struct Point1
|
||||
{
|
||||
import std.range.primitives : isOutputRange, put;
|
||||
|
||||
int x, y;
|
||||
|
||||
void toString(W)(ref W writer, scope const ref FormatSpec!char f)
|
||||
if (isOutputRange!(W, char))
|
||||
{
|
||||
put(writer, "(");
|
||||
formatValue(writer, x, f);
|
||||
put(writer, ",");
|
||||
formatValue(writer, y, f);
|
||||
put(writer, ")");
|
||||
}
|
||||
}
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%s");
|
||||
auto p1 = Point1(16, 11);
|
||||
|
||||
formatValue(w1, p1, spec1);
|
||||
assert(w1.data == "(16,11)");
|
||||
|
||||
// Using a `toString` with a sink
|
||||
static struct Point2
|
||||
{
|
||||
int x, y;
|
||||
|
||||
void toString(scope void delegate(scope const(char)[]) @safe sink,
|
||||
scope const FormatSpec!char fmt) const
|
||||
{
|
||||
sink("(");
|
||||
sink.formatValue(x, fmt);
|
||||
sink(",");
|
||||
sink.formatValue(y, fmt);
|
||||
sink(")");
|
||||
}
|
||||
}
|
||||
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%03d");
|
||||
auto p2 = Point2(16,11);
|
||||
|
||||
formatValue(w2, p2, spec2);
|
||||
assert(w2.data == "(016,011)");
|
||||
|
||||
// Using `string toString()`
|
||||
static struct Point3
|
||||
{
|
||||
int x, y;
|
||||
|
||||
string toString()
|
||||
{
|
||||
import std.conv : to;
|
||||
|
||||
return "(" ~ to!string(x) ~ "," ~ to!string(y) ~ ")";
|
||||
}
|
||||
}
|
||||
|
||||
auto w3 = appender!string();
|
||||
auto spec3 = singleSpec("%s"); // has to be %s
|
||||
auto p3 = Point3(16,11);
|
||||
|
||||
formatValue(w3, p3, spec3);
|
||||
assert(w3.data == "(16,11)");
|
||||
|
||||
// without `toString`
|
||||
static struct Point4
|
||||
{
|
||||
int x, y;
|
||||
}
|
||||
|
||||
auto w4 = appender!string();
|
||||
auto spec4 = singleSpec("%s"); // has to be %s
|
||||
auto p4 = Point4(16,11);
|
||||
|
||||
formatValue(w4, p4, spec3);
|
||||
assert(w4.data == "Point4(16, 11)");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w1 = appender!string();
|
||||
auto spec1 = singleSpec("%s");
|
||||
auto p1 = () @trusted { return cast(void*) 0xFFEECCAA; } ();
|
||||
formatValue(w1, p1, spec1);
|
||||
|
||||
assert(w1.data == "FFEECCAA");
|
||||
|
||||
// null pointers are printed as `"null"` when used with `%s` and as hexadecimal integer else
|
||||
auto w2 = appender!string();
|
||||
auto spec2 = singleSpec("%s");
|
||||
auto p2 = () @trusted { return cast(void*) 0x00000000; } ();
|
||||
formatValue(w2, p2, spec2);
|
||||
|
||||
assert(w2.data == "null");
|
||||
|
||||
auto w3 = appender!string();
|
||||
auto spec3 = singleSpec("%x");
|
||||
formatValue(w3, p2, spec3);
|
||||
|
||||
assert(w3.data == "0");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import core.simd; // cannot be selective, because float4 might not be defined
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto w = appender!string();
|
||||
auto spec = singleSpec("%s");
|
||||
|
||||
static if (is(float4))
|
||||
{
|
||||
version (X86) {}
|
||||
else
|
||||
{
|
||||
float4 f4;
|
||||
f4.array[0] = 1;
|
||||
f4.array[1] = 2;
|
||||
f4.array[2] = 3;
|
||||
f4.array[3] = 4;
|
||||
|
||||
formatValue(w, f4, spec);
|
||||
assert(w.data == "[1, 2, 3, 4]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
|
||||
auto writer1 = appender!string();
|
||||
formattedWrite(writer1, "%s is the ultimate %s.", 42, "answer");
|
||||
assert(writer1[] == "42 is the ultimate answer.");
|
||||
|
||||
auto writer2 = appender!string();
|
||||
formattedWrite(writer2, "Increase: %7.2f %%", 17.4285);
|
||||
assert(writer2[] == "Increase: 17.43 %");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
|
||||
auto writer = appender!string();
|
||||
writer.formattedWrite!"%d is the ultimate %s."(42, "answer");
|
||||
assert(writer[] == "42 is the ultimate answer.");
|
||||
|
||||
// This line doesn't compile, because 3.14 cannot be formatted with %d:
|
||||
// writer.formattedWrite!"%d is the ultimate %s."(3.14, "answer");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.format.write;
|
||||
|
||||
import std.array : appender;
|
||||
import std.format.spec : singleSpec;
|
||||
|
||||
auto writer = appender!string();
|
||||
auto spec = singleSpec("%08b");
|
||||
writer.formatValue(42, spec);
|
||||
assert(writer.data == "00101010");
|
||||
|
||||
spec = singleSpec("%2s");
|
||||
writer.formatValue('=', spec);
|
||||
assert(writer.data == "00101010 =");
|
||||
|
||||
spec = singleSpec("%+14.6e");
|
||||
writer.formatValue(42.0, spec);
|
||||
assert(writer.data == "00101010 = +4.200000e+01");
|
||||
}
|
||||
|
360
libphobos/testsuite/libphobos.phobos/std_functional.d
Normal file
360
libphobos/testsuite/libphobos.phobos/std_functional.d
Normal file
|
@ -0,0 +1,360 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
// Strings are compiled into functions:
|
||||
alias isEven = unaryFun!("(a & 1) == 0");
|
||||
assert(isEven(2) && !isEven(1));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
alias less = binaryFun!("a < b");
|
||||
assert(less(1, 2) && !less(2, 1));
|
||||
alias greater = binaryFun!("a > b");
|
||||
assert(!greater("1", "2") && greater("2", "1"));
|
||||
}
|
||||
|
||||
pure @safe @nogc nothrow unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
assert(lessThan(2, 3));
|
||||
assert(lessThan(2U, 3U));
|
||||
assert(lessThan(2, 3.0));
|
||||
assert(lessThan(-2, 3U));
|
||||
assert(lessThan(2, 3U));
|
||||
assert(!lessThan(3U, -2));
|
||||
assert(!lessThan(3U, 2));
|
||||
assert(!lessThan(0, 0));
|
||||
assert(!lessThan(0U, 0));
|
||||
assert(!lessThan(0, 0U));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
assert(!greaterThan(2, 3));
|
||||
assert(!greaterThan(2U, 3U));
|
||||
assert(!greaterThan(2, 3.0));
|
||||
assert(!greaterThan(-2, 3U));
|
||||
assert(!greaterThan(2, 3U));
|
||||
assert(greaterThan(3U, -2));
|
||||
assert(greaterThan(3U, 2));
|
||||
assert(!greaterThan(0, 0));
|
||||
assert(!greaterThan(0U, 0));
|
||||
assert(!greaterThan(0, 0U));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
assert(equalTo(0U, 0));
|
||||
assert(equalTo(0, 0U));
|
||||
assert(!equalTo(-1, ~0U));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
alias gt = reverseArgs!(binaryFun!("a < b"));
|
||||
assert(gt(2, 1) && !gt(1, 1));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
int x = 42;
|
||||
bool xyz(int a, int b) { return a * x < b / x; }
|
||||
auto foo = &xyz;
|
||||
foo(4, 5);
|
||||
alias zyx = reverseArgs!(foo);
|
||||
assert(zyx(5, 4) == foo(4, 5));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
alias gt = reverseArgs!(binaryFun!("a < b"));
|
||||
assert(gt(2, 1) && !gt(1, 1));
|
||||
int x = 42;
|
||||
bool xyz(int a, int b) { return a * x < b / x; }
|
||||
auto foo = &xyz;
|
||||
foo(4, 5);
|
||||
alias zyx = reverseArgs!(foo);
|
||||
assert(zyx(5, 4) == foo(4, 5));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
int abc(int a, int b, int c) { return a * b + c; }
|
||||
alias cba = reverseArgs!abc;
|
||||
assert(abc(91, 17, 32) == cba(32, 17, 91));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
int a(int a) { return a * 2; }
|
||||
alias _a = reverseArgs!a;
|
||||
assert(a(2) == _a(2));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
int b() { return 4; }
|
||||
alias _b = reverseArgs!b;
|
||||
assert(b() == _b());
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
import std.algorithm.searching : find;
|
||||
import std.uni : isWhite;
|
||||
string a = " Hello, world!";
|
||||
assert(find!(not!isWhite)(a) == "Hello, world!");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
int fun(int a, int b) { return a + b; }
|
||||
alias fun5 = partial!(fun, 5);
|
||||
assert(fun5(6) == 11);
|
||||
// Note that in most cases you'd use an alias instead of a value
|
||||
// assignment. Using an alias allows you to partially evaluate template
|
||||
// functions without committing to a particular type of the function.
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
// Overloads are resolved when the partially applied function is called
|
||||
// with the remaining arguments.
|
||||
struct S
|
||||
{
|
||||
static char fun(int i, string s) { return s[i]; }
|
||||
static int fun(int a, int b) { return a * b; }
|
||||
}
|
||||
alias fun3 = partial!(S.fun, 3);
|
||||
assert(fun3("hello") == 'l');
|
||||
assert(fun3(10) == 30);
|
||||
}
|
||||
|
||||
pure @safe @nogc nothrow unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
int f(int x, int y, int z)
|
||||
{
|
||||
return x + y + z;
|
||||
}
|
||||
auto cf = curry!f;
|
||||
auto cf1 = cf(1);
|
||||
auto cf2 = cf(2);
|
||||
|
||||
assert(cf1(2)(3) == f(1, 2, 3));
|
||||
assert(cf2(2)(3) == f(2, 2, 3));
|
||||
}
|
||||
|
||||
pure @safe @nogc nothrow unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
//works with callable structs too
|
||||
struct S
|
||||
{
|
||||
int w;
|
||||
int opCall(int x, int y, int z)
|
||||
{
|
||||
return w + x + y + z;
|
||||
}
|
||||
}
|
||||
|
||||
S s;
|
||||
s.w = 5;
|
||||
|
||||
auto cs = curry(s);
|
||||
auto cs1 = cs(1);
|
||||
auto cs2 = cs(2);
|
||||
|
||||
assert(cs1(2)(3) == s(1, 2, 3));
|
||||
assert(cs1(2)(3) == (1 + 2 + 3 + 5));
|
||||
assert(cs2(2)(3) ==s(2, 2, 3));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
import std.typecons : Tuple;
|
||||
static bool f1(int a) { return a != 0; }
|
||||
static int f2(int a) { return a / 2; }
|
||||
auto x = adjoin!(f1, f2)(5);
|
||||
assert(is(typeof(x) == Tuple!(bool, int)));
|
||||
assert(x[0] == true && x[1] == 2);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.iteration : map;
|
||||
import std.array : split;
|
||||
import std.conv : to;
|
||||
|
||||
// First split a string in whitespace-separated tokens and then
|
||||
// convert each token into an integer
|
||||
assert(compose!(map!(to!(int)), split)("1 2 3").equal([1, 2, 3]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
import std.conv : to;
|
||||
string foo(int a) { return to!(string)(a); }
|
||||
int bar(string a) { return to!(int)(a) + 1; }
|
||||
double baz(int a) { return a + 0.5; }
|
||||
assert(compose!(baz, bar, foo)(1) == 2.5);
|
||||
assert(pipe!(foo, bar, baz)(1) == 2.5);
|
||||
|
||||
assert(compose!(baz, `to!(int)(a) + 1`, foo)(1) == 2.5);
|
||||
assert(compose!(baz, bar)("1"[]) == 2.5);
|
||||
|
||||
assert(compose!(baz, bar)("1") == 2.5);
|
||||
|
||||
assert(compose!(`a + 0.5`, `to!(int)(a) + 1`, foo)(1) == 2.5);
|
||||
}
|
||||
|
||||
@safe nothrow unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
ulong fib(ulong n) @safe nothrow
|
||||
{
|
||||
return n < 2 ? n : memoize!fib(n - 2) + memoize!fib(n - 1);
|
||||
}
|
||||
assert(fib(10) == 55);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
ulong fact(ulong n) @safe
|
||||
{
|
||||
return n < 2 ? 1 : n * memoize!fact(n - 1);
|
||||
}
|
||||
assert(fact(10) == 3628800);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
ulong factImpl(ulong n) @safe
|
||||
{
|
||||
return n < 2 ? 1 : n * factImpl(n - 1);
|
||||
}
|
||||
alias fact = memoize!factImpl;
|
||||
assert(fact(10) == 3628800);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
ulong fact(ulong n)
|
||||
{
|
||||
// Memoize no more than 8 values
|
||||
return n < 2 ? 1 : n * memoize!(fact, 8)(n - 1);
|
||||
}
|
||||
assert(fact(8) == 40320);
|
||||
// using more entries than maxSize will overwrite existing entries
|
||||
assert(fact(10) == 3628800);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
static int inc(ref uint num) {
|
||||
num++;
|
||||
return 8675309;
|
||||
}
|
||||
|
||||
uint myNum = 0;
|
||||
auto incMyNumDel = toDelegate(&inc);
|
||||
auto returnVal = incMyNumDel(myNum);
|
||||
assert(myNum == 1);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto name = tuple("John", "Doe");
|
||||
string full = name.bind!((first, last) => first ~ " " ~ last);
|
||||
assert(full == "John Doe");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
import std.algorithm.comparison : min, max;
|
||||
|
||||
struct Pair
|
||||
{
|
||||
int a;
|
||||
int b;
|
||||
}
|
||||
|
||||
auto p = Pair(123, 456);
|
||||
assert(p.bind!min == 123); // min(p.a, p.b)
|
||||
assert(p.bind!max == 456); // max(p.a, p.b)
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.functional;
|
||||
|
||||
import std.algorithm.iteration : map, filter;
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.typecons : tuple;
|
||||
|
||||
auto ages = [
|
||||
tuple("Alice", 35),
|
||||
tuple("Bob", 64),
|
||||
tuple("Carol", 21),
|
||||
tuple("David", 39),
|
||||
tuple("Eve", 50)
|
||||
];
|
||||
|
||||
auto overForty = ages
|
||||
.filter!(bind!((name, age) => age > 40))
|
||||
.map!(bind!((name, age) => name));
|
||||
|
||||
assert(overForty.equal(["Bob", "Eve"]));
|
||||
}
|
||||
|
18
libphobos/testsuite/libphobos.phobos/std_getopt.d
Normal file
18
libphobos/testsuite/libphobos.phobos/std_getopt.d
Normal file
|
@ -0,0 +1,18 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.getopt;
|
||||
|
||||
auto args = ["prog", "--foo", "-b"];
|
||||
|
||||
bool foo;
|
||||
bool bar;
|
||||
auto rslt = getopt(args, "foo|f", "Some information about foo.", &foo, "bar|b",
|
||||
"Some help message about bar.", &bar);
|
||||
|
||||
if (rslt.helpWanted)
|
||||
{
|
||||
defaultGetoptPrinter("Some information about the program.",
|
||||
rslt.options);
|
||||
}
|
||||
}
|
||||
|
128
libphobos/testsuite/libphobos.phobos/std_int128.d
Normal file
128
libphobos/testsuite/libphobos.phobos/std_int128.d
Normal file
|
@ -0,0 +1,128 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.int128;
|
||||
|
||||
const Int128 a = Int128(0xffff_ffff_ffff_ffffL, 0x0123_4567_89ab_cdefL);
|
||||
assert(cast(long) a == 0x0123_4567_89ab_cdefL);
|
||||
assert(cast(int) a == 0x89ab_cdef);
|
||||
assert(cast(byte) a == cast(byte) 0xef);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.int128;
|
||||
|
||||
const Int128 a = Int128(-1L << 60);
|
||||
assert(cast(double) a == -(2.0 ^^ 60));
|
||||
assert(cast(double) (a * a) == 2.0 ^^ 120);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.int128;
|
||||
|
||||
import std.format : format;
|
||||
|
||||
assert(format("%s", Int128.max) == "170141183460469231731687303715884105727");
|
||||
assert(format("%s", Int128.min) == "-170141183460469231731687303715884105728");
|
||||
assert(format("%x", Int128.max) == "7fffffffffffffffffffffffffffffff");
|
||||
assert(format("%X", Int128.max) == "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF");
|
||||
assert(format("%032X", Int128(123L)) == "0000000000000000000000000000007B");
|
||||
assert(format("%+ 40d", Int128(123L)) == " +123");
|
||||
assert(format("%+-40d", Int128(123L)) == "+123 ");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.int128;
|
||||
|
||||
import std.conv : to;
|
||||
|
||||
assert(to!wstring(Int128.max) == "170141183460469231731687303715884105727"w);
|
||||
assert(to!dstring(Int128.max) == "170141183460469231731687303715884105727"d);
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.int128;
|
||||
|
||||
Int128 c = Int128(5, 6);
|
||||
assert(c == c);
|
||||
assert(c == +c);
|
||||
assert(c == - -c);
|
||||
assert(~c == Int128(~5, ~6));
|
||||
++c;
|
||||
assert(c == Int128(5, 7));
|
||||
assert(--c == Int128(5, 6));
|
||||
assert(!!c);
|
||||
assert(!Int128());
|
||||
|
||||
assert(c + Int128(10, 20) == Int128(15, 26));
|
||||
assert(c - Int128(1, 2) == Int128(4, 4));
|
||||
assert(c * Int128(100, 2) == Int128(610, 12));
|
||||
assert(c / Int128(3, 2) == Int128(0, 1));
|
||||
assert(c % Int128(3, 2) == Int128(2, 4));
|
||||
assert((c & Int128(3, 2)) == Int128(1, 2));
|
||||
assert((c | Int128(3, 2)) == Int128(7, 6));
|
||||
assert((c ^ Int128(3, 2)) == Int128(6, 4));
|
||||
|
||||
assert(c + 15 == Int128(5, 21));
|
||||
assert(c - 15 == Int128(4, -9));
|
||||
assert(c * 15 == Int128(75, 90));
|
||||
assert(c / 15 == Int128(0, 6148914691236517205));
|
||||
assert(c % 15 == Int128(0, 11));
|
||||
assert((c & 15) == Int128(0, 6));
|
||||
assert((c | 15) == Int128(5, 15));
|
||||
assert((c ^ 15) == Int128(5, 9));
|
||||
|
||||
assert(15 + c == Int128(5, 21));
|
||||
assert(15 - c == Int128(-5, 9));
|
||||
assert(15 * c == Int128(75, 90));
|
||||
assert(15 / c == Int128(0, 0));
|
||||
assert(15 % c == Int128(0, 15));
|
||||
assert((15 & c) == Int128(0, 6));
|
||||
assert((15 | c) == Int128(5, 15));
|
||||
assert((15 ^ c) == Int128(5, 9));
|
||||
|
||||
assert(c << 1 == Int128(10, 12));
|
||||
assert(-c >> 1 == Int128(-3, 9223372036854775805));
|
||||
assert(-c >>> 1 == Int128(9223372036854775805, 9223372036854775805));
|
||||
|
||||
assert((c += 1) == Int128(5, 7));
|
||||
assert((c -= 1) == Int128(5, 6));
|
||||
assert((c += Int128(0, 1)) == Int128(5, 7));
|
||||
assert((c -= Int128(0, 1)) == Int128(5, 6));
|
||||
assert((c *= 2) == Int128(10, 12));
|
||||
assert((c /= 2) == Int128(5, 6));
|
||||
assert((c %= 2) == Int128());
|
||||
c += Int128(5, 6);
|
||||
assert((c *= Int128(10, 20)) == Int128(160, 120));
|
||||
assert((c /= Int128(10, 20)) == Int128(0, 15));
|
||||
c += Int128(72, 0);
|
||||
assert((c %= Int128(10, 20)) == Int128(1, -125));
|
||||
assert((c &= Int128(3, 20)) == Int128(1, 0));
|
||||
assert((c |= Int128(8, 2)) == Int128(9, 2));
|
||||
assert((c ^= Int128(8, 2)) == Int128(1, 0));
|
||||
c |= Int128(10, 5);
|
||||
assert((c <<= 1) == Int128(11 * 2, 5 * 2));
|
||||
assert((c >>>= 1) == Int128(11, 5));
|
||||
c = Int128(long.min, long.min);
|
||||
assert((c >>= 1) == Int128(long.min >> 1, cast(ulong) long.min >> 1));
|
||||
|
||||
assert(-Int128.min == Int128.min);
|
||||
assert(Int128.max + 1 == Int128.min);
|
||||
|
||||
c = Int128(5, 6);
|
||||
assert(c < Int128(6, 5));
|
||||
assert(c > 10);
|
||||
|
||||
c = Int128(-1UL);
|
||||
assert(c == -1UL);
|
||||
c = Int128(-1L);
|
||||
assert(c == -1L);
|
||||
}
|
||||
|
47
libphobos/testsuite/libphobos.phobos/std_internal_cstring.d
Normal file
47
libphobos/testsuite/libphobos.phobos/std_internal_cstring.d
Normal file
|
@ -0,0 +1,47 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.internal.cstring;
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
import core.stdc.stdlib : free;
|
||||
import core.sys.posix.stdlib : setenv;
|
||||
import std.exception : enforce;
|
||||
|
||||
void setEnvironment(scope const(char)[] name, scope const(char)[] value)
|
||||
{ enforce(setenv(name.tempCString(), value.tempCString(), 1) != -1); }
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
import core.sys.windows.winbase : SetEnvironmentVariableW;
|
||||
import std.exception : enforce;
|
||||
|
||||
void setEnvironment(scope const(char)[] name, scope const(char)[] value)
|
||||
{ enforce(SetEnvironmentVariableW(name.tempCStringW(), value.tempCStringW())); }
|
||||
}
|
||||
}
|
||||
|
||||
nothrow @nogc @system unittest
|
||||
{
|
||||
import std.internal.cstring;
|
||||
|
||||
import core.stdc.string;
|
||||
|
||||
string str = "abc";
|
||||
|
||||
// Intended usage
|
||||
assert(strlen(str.tempCString()) == 3);
|
||||
|
||||
// Correct usage
|
||||
auto tmp = str.tempCString();
|
||||
assert(strlen(tmp) == 3); // or `tmp.ptr`, or `tmp.buffPtr`
|
||||
|
||||
// $(RED WARNING): $(RED Incorrect usage)
|
||||
auto pInvalid1 = str.tempCString().ptr;
|
||||
const char* pInvalid2 = str.tempCString();
|
||||
// Both pointers refer to invalid memory here as
|
||||
// returned values aren't assigned to a variable and
|
||||
// both primary expressions are ended.
|
||||
}
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.internal.scopebuffer;
|
||||
|
||||
ubyte[10] tmpbuf = void;
|
||||
auto sb = scopeBuffer(tmpbuf);
|
||||
scope(exit) sb.free();
|
||||
}
|
||||
|
252
libphobos/testsuite/libphobos.phobos/std_json.d
Normal file
252
libphobos/testsuite/libphobos.phobos/std_json.d
Normal file
|
@ -0,0 +1,252 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
import std.conv : to;
|
||||
|
||||
// parse a file or string of json into a usable structure
|
||||
string s = `{ "language": "D", "rating": 3.5, "code": "42" }`;
|
||||
JSONValue j = parseJSON(s);
|
||||
// j and j["language"] return JSONValue,
|
||||
// j["language"].str returns a string
|
||||
assert(j["language"].str == "D");
|
||||
assert(j["rating"].floating == 3.5);
|
||||
|
||||
// check a type
|
||||
long x;
|
||||
if (const(JSONValue)* code = "code" in j)
|
||||
{
|
||||
if (code.type() == JSONType.integer)
|
||||
x = code.integer;
|
||||
else
|
||||
x = to!int(code.str);
|
||||
}
|
||||
|
||||
// create a json struct
|
||||
JSONValue jj = [ "language": "D" ];
|
||||
// rating doesnt exist yet, so use .object to assign
|
||||
jj.object["rating"] = JSONValue(3.5);
|
||||
// create an array to assign to list
|
||||
jj.object["list"] = JSONValue( ["a", "b", "c"] );
|
||||
// list already exists, so .object optional
|
||||
jj["list"].array ~= JSONValue("D");
|
||||
|
||||
string jjStr = `{"language":"D","list":["a","b","c","D"],"rating":3.5}`;
|
||||
assert(jj.toString == jjStr);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
string s = "{ \"language\": \"D\" }";
|
||||
JSONValue j = parseJSON(s);
|
||||
assert(j.type == JSONType.object);
|
||||
assert(j["language"].type == JSONType.string);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue j = [ "language": "D" ];
|
||||
|
||||
// get value
|
||||
assert(j["language"].str == "D");
|
||||
|
||||
// change existing key to new string
|
||||
j["language"].str = "Perl";
|
||||
assert(j["language"].str == "Perl");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue j = true;
|
||||
assert(j.boolean == true);
|
||||
|
||||
j.boolean = false;
|
||||
assert(j.boolean == false);
|
||||
|
||||
j.integer = 12;
|
||||
import std.exception : assertThrown;
|
||||
assertThrown!JSONException(j.boolean);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
import std.exception;
|
||||
import std.conv;
|
||||
string s =
|
||||
`{
|
||||
"a": 123,
|
||||
"b": 3.1415,
|
||||
"c": "text",
|
||||
"d": true,
|
||||
"e": [1, 2, 3],
|
||||
"f": { "a": 1 },
|
||||
"g": -45,
|
||||
"h": ` ~ ulong.max.to!string ~ `,
|
||||
}`;
|
||||
|
||||
struct a { }
|
||||
|
||||
immutable json = parseJSON(s);
|
||||
assert(json["a"].get!double == 123.0);
|
||||
assert(json["a"].get!int == 123);
|
||||
assert(json["a"].get!uint == 123);
|
||||
assert(json["b"].get!double == 3.1415);
|
||||
assertThrown!JSONException(json["b"].get!int);
|
||||
assert(json["c"].get!string == "text");
|
||||
assert(json["d"].get!bool == true);
|
||||
assertNotThrown(json["e"].get!(JSONValue[]));
|
||||
assertNotThrown(json["f"].get!(JSONValue[string]));
|
||||
static assert(!__traits(compiles, json["a"].get!a));
|
||||
assertThrown!JSONException(json["e"].get!float);
|
||||
assertThrown!JSONException(json["d"].get!(JSONValue[string]));
|
||||
assertThrown!JSONException(json["f"].get!(JSONValue[]));
|
||||
assert(json["g"].get!int == -45);
|
||||
assertThrown!ConvException(json["g"].get!uint);
|
||||
assert(json["h"].get!ulong == ulong.max);
|
||||
assertThrown!ConvException(json["h"].get!uint);
|
||||
assertNotThrown(json["h"].get!float);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue j = JSONValue( "a string" );
|
||||
j = JSONValue(42);
|
||||
|
||||
j = JSONValue( [1, 2, 3] );
|
||||
assert(j.type == JSONType.array);
|
||||
|
||||
j = JSONValue( ["language": "D"] );
|
||||
assert(j.type == JSONType.object);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue obj1 = JSONValue.emptyObject;
|
||||
assert(obj1.type == JSONType.object);
|
||||
obj1.object["a"] = JSONValue(1);
|
||||
assert(obj1.object["a"] == JSONValue(1));
|
||||
|
||||
JSONValue obj2 = JSONValue.emptyObject;
|
||||
assert("a" !in obj2.object);
|
||||
obj2.object["b"] = JSONValue(5);
|
||||
assert(obj1 != obj2);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue obj = JSONValue.emptyOrderedObject;
|
||||
assert(obj.type == JSONType.object);
|
||||
assert(obj.isOrdered);
|
||||
obj["b"] = JSONValue(2);
|
||||
obj["a"] = JSONValue(1);
|
||||
assert(obj["a"] == JSONValue(1));
|
||||
assert(obj["b"] == JSONValue(2));
|
||||
|
||||
string[] keys;
|
||||
foreach (string k, JSONValue v; obj)
|
||||
keys ~= k;
|
||||
assert(keys == ["b", "a"]);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue arr1 = JSONValue.emptyArray;
|
||||
assert(arr1.type == JSONType.array);
|
||||
assert(arr1.array.length == 0);
|
||||
arr1.array ~= JSONValue("Hello");
|
||||
assert(arr1.array.length == 1);
|
||||
assert(arr1.array[0] == JSONValue("Hello"));
|
||||
|
||||
JSONValue arr2 = JSONValue.emptyArray;
|
||||
assert(arr2.array.length == 0);
|
||||
assert(arr1 != arr2);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue j = JSONValue( [42, 43, 44] );
|
||||
assert( j[0].integer == 42 );
|
||||
assert( j[1].integer == 43 );
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue j = JSONValue( ["language": "D"] );
|
||||
assert( j["language"].str == "D" );
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue j = JSONValue( ["language": "D"] );
|
||||
j["language"].str = "Perl";
|
||||
assert( j["language"].str == "Perl" );
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue j = JSONValue( ["Perl", "C"] );
|
||||
j[1].str = "D";
|
||||
assert( j[1].str == "D" );
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
JSONValue j = [ "language": "D", "author": "walter" ];
|
||||
string a = ("author" in j).str;
|
||||
*("author" in j) = "Walter";
|
||||
assert(j["author"].str == "Walter");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.json;
|
||||
|
||||
assert(JSONValue(10).opEquals(JSONValue(10.0)));
|
||||
assert(JSONValue(10) != (JSONValue(10.5)));
|
||||
|
||||
assert(JSONValue(1) != JSONValue(true));
|
||||
assert(JSONValue.emptyArray != JSONValue.emptyObject);
|
||||
|
||||
assert(parseJSON(`{"a": 1, "b": 2}`).opEquals(parseJSON(`{"b": 2, "a": 1}`)));
|
||||
|
||||
}
|
||||
|
22
libphobos/testsuite/libphobos.phobos/std_logger_core.d
Normal file
22
libphobos/testsuite/libphobos.phobos/std_logger_core.d
Normal file
|
@ -0,0 +1,22 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.logger.core;
|
||||
|
||||
auto nl1 = new StdForwardLogger(LogLevel.all);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.logger.core;
|
||||
|
||||
import std.logger.filelogger : FileLogger;
|
||||
import std.file : deleteme, remove;
|
||||
Logger l = stdThreadLocalLog;
|
||||
stdThreadLocalLog = new FileLogger(deleteme ~ "-someFile.log");
|
||||
scope(exit) remove(deleteme ~ "-someFile.log");
|
||||
|
||||
auto tempLog = stdThreadLocalLog;
|
||||
stdThreadLocalLog = l;
|
||||
destroy(tempLog);
|
||||
}
|
||||
|
10
libphobos/testsuite/libphobos.phobos/std_logger_nulllogger.d
Normal file
10
libphobos/testsuite/libphobos.phobos/std_logger_nulllogger.d
Normal file
|
@ -0,0 +1,10 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.logger.nulllogger;
|
||||
|
||||
import std.logger.core : LogLevel;
|
||||
auto nl1 = new NullLogger(LogLevel.all);
|
||||
nl1.info("You will never read this.");
|
||||
nl1.fatal("You will never read this, either and it will not throw");
|
||||
}
|
||||
|
163
libphobos/testsuite/libphobos.phobos/std_math_algebraic.d
Normal file
163
libphobos/testsuite/libphobos.phobos/std_math_algebraic.d
Normal file
|
@ -0,0 +1,163 @@
|
|||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
import std.math.traits : isIdentical, isNaN;
|
||||
|
||||
assert(isIdentical(abs(-0.0L), 0.0L));
|
||||
assert(isNaN(abs(real.nan)));
|
||||
assert(abs(-real.infinity) == real.infinity);
|
||||
assert(abs(-56) == 56);
|
||||
assert(abs(2321312L) == 2321312L);
|
||||
assert(abs(23u) == 23u);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
import std.math.traits : isIdentical;
|
||||
|
||||
assert(isIdentical(fabs(0.0f), 0.0f));
|
||||
assert(isIdentical(fabs(-0.0f), 0.0f));
|
||||
assert(fabs(-10.0f) == 10.0f);
|
||||
|
||||
assert(isIdentical(fabs(0.0), 0.0));
|
||||
assert(isIdentical(fabs(-0.0), 0.0));
|
||||
assert(fabs(-10.0) == 10.0);
|
||||
|
||||
assert(isIdentical(fabs(0.0L), 0.0L));
|
||||
assert(isIdentical(fabs(-0.0L), 0.0L));
|
||||
assert(fabs(-10.0L) == 10.0L);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
assert(sqrt(2.0).feqrel(1.4142) > 16);
|
||||
assert(sqrt(9.0).feqrel(3.0) > 16);
|
||||
|
||||
assert(isNaN(sqrt(-1.0f)));
|
||||
assert(isNaN(sqrt(-1.0)));
|
||||
assert(isNaN(sqrt(-1.0L)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
|
||||
assert(cbrt(1.0).feqrel(1.0) > 16);
|
||||
assert(cbrt(27.0).feqrel(3.0) > 16);
|
||||
assert(cbrt(15.625).feqrel(2.5) > 16);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
|
||||
assert(hypot(1.0, 1.0).feqrel(1.4142) > 16);
|
||||
assert(hypot(3.0, 4.0).feqrel(5.0) > 16);
|
||||
assert(hypot(real.infinity, 1.0L) == real.infinity);
|
||||
assert(hypot(real.infinity, real.nan) == real.infinity);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
assert(isClose(hypot(1.0, 2.0, 2.0), 3.0));
|
||||
assert(isClose(hypot(2.0, 3.0, 6.0), 7.0));
|
||||
assert(isClose(hypot(1.0, 4.0, 8.0), 9.0));
|
||||
}
|
||||
|
||||
@safe nothrow @nogc unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
real x = 3.1L;
|
||||
static real[] pp = [56.1L, 32.7L, 6];
|
||||
|
||||
assert(poly(x, pp) == (56.1L + (32.7L + 6.0L * x) * x));
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
assert(nextPow2(2) == 4);
|
||||
assert(nextPow2(10) == 16);
|
||||
assert(nextPow2(4000) == 4096);
|
||||
|
||||
assert(nextPow2(-2) == -4);
|
||||
assert(nextPow2(-10) == -16);
|
||||
|
||||
assert(nextPow2(uint.max) == 0);
|
||||
assert(nextPow2(uint.min) == 0);
|
||||
assert(nextPow2(size_t.max) == 0);
|
||||
assert(nextPow2(size_t.min) == 0);
|
||||
|
||||
assert(nextPow2(int.max) == 0);
|
||||
assert(nextPow2(int.min) == 0);
|
||||
assert(nextPow2(long.max) == 0);
|
||||
assert(nextPow2(long.min) == 0);
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
assert(nextPow2(2.1) == 4.0);
|
||||
assert(nextPow2(-2.0) == -4.0);
|
||||
assert(nextPow2(0.25) == 0.5);
|
||||
assert(nextPow2(-4.0) == -8.0);
|
||||
|
||||
assert(nextPow2(double.max) == 0.0);
|
||||
assert(nextPow2(double.infinity) == double.infinity);
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
assert(truncPow2(3) == 2);
|
||||
assert(truncPow2(4) == 4);
|
||||
assert(truncPow2(10) == 8);
|
||||
assert(truncPow2(4000) == 2048);
|
||||
|
||||
assert(truncPow2(-5) == -4);
|
||||
assert(truncPow2(-20) == -16);
|
||||
|
||||
assert(truncPow2(uint.max) == int.max + 1);
|
||||
assert(truncPow2(uint.min) == 0);
|
||||
assert(truncPow2(ulong.max) == long.max + 1);
|
||||
assert(truncPow2(ulong.min) == 0);
|
||||
|
||||
assert(truncPow2(int.max) == (int.max / 2) + 1);
|
||||
assert(truncPow2(int.min) == int.min);
|
||||
assert(truncPow2(long.max) == (long.max / 2) + 1);
|
||||
assert(truncPow2(long.min) == long.min);
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.math.algebraic;
|
||||
|
||||
assert(truncPow2(2.1) == 2.0);
|
||||
assert(truncPow2(7.0) == 4.0);
|
||||
assert(truncPow2(-1.9) == -1.0);
|
||||
assert(truncPow2(0.24) == 0.125);
|
||||
assert(truncPow2(-7.0) == -4.0);
|
||||
|
||||
assert(truncPow2(double.infinity) == double.infinity);
|
||||
}
|
||||
|
279
libphobos/testsuite/libphobos.phobos/std_math_exponential.d
Normal file
279
libphobos/testsuite/libphobos.phobos/std_math_exponential.d
Normal file
|
@ -0,0 +1,279 @@
|
|||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
|
||||
assert(pow(2.0, 5) == 32.0);
|
||||
assert(pow(1.5, 9).feqrel(38.4433) > 16);
|
||||
assert(pow(real.nan, 2) is real.nan);
|
||||
assert(pow(real.infinity, 2) == real.infinity);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
assert(pow(2, 3) == 8);
|
||||
assert(pow(3, 2) == 9);
|
||||
|
||||
assert(pow(2, 10) == 1_024);
|
||||
assert(pow(2, 20) == 1_048_576);
|
||||
assert(pow(2, 30) == 1_073_741_824);
|
||||
|
||||
assert(pow(0, 0) == 1);
|
||||
|
||||
assert(pow(1, -5) == 1);
|
||||
assert(pow(1, -6) == 1);
|
||||
assert(pow(-1, -5) == -1);
|
||||
assert(pow(-1, -6) == 1);
|
||||
|
||||
assert(pow(-2, 5) == -32);
|
||||
assert(pow(-2, -5) == 0);
|
||||
assert(pow(cast(double) -2, -5) == -0.03125);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
assert(pow(2, 5.0) == 32.0);
|
||||
assert(pow(7, 3.0) == 343.0);
|
||||
assert(pow(2, real.nan) is real.nan);
|
||||
assert(pow(2, real.infinity) == real.infinity);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
assert(isClose(pow(2.0, 3.0), 8.0));
|
||||
assert(isClose(pow(1.5, 10.0), 57.6650390625));
|
||||
|
||||
// square root of 9
|
||||
assert(isClose(pow(9.0, 0.5), 3.0));
|
||||
// 10th root of 1024
|
||||
assert(isClose(pow(1024.0, 0.1), 2.0));
|
||||
|
||||
assert(isClose(pow(-4.0, 3.0), -64.0));
|
||||
|
||||
// reciprocal of 4 ^^ 2
|
||||
assert(isClose(pow(4.0, -2.0), 0.0625));
|
||||
// reciprocal of (-2) ^^ 3
|
||||
assert(isClose(pow(-2.0, -3.0), -0.125));
|
||||
|
||||
assert(isClose(pow(-2.5, 3.0), -15.625));
|
||||
// reciprocal of 2.5 ^^ 3
|
||||
assert(isClose(pow(2.5, -3.0), 0.064));
|
||||
// reciprocal of (-2.5) ^^ 3
|
||||
assert(isClose(pow(-2.5, -3.0), -0.064));
|
||||
|
||||
// reciprocal of square root of 4
|
||||
assert(isClose(pow(4.0, -0.5), 0.5));
|
||||
|
||||
// per definition
|
||||
assert(isClose(pow(0.0, 0.0), 1.0));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
// the result is a complex number
|
||||
// which cannot be represented as floating point number
|
||||
import std.math.traits : isNaN;
|
||||
assert(isNaN(pow(-2.5, -1.5)));
|
||||
|
||||
// use the ^^-operator of std.complex instead
|
||||
import std.complex : complex;
|
||||
auto c1 = complex(-2.5, 0.0);
|
||||
auto c2 = complex(-1.5, 0.0);
|
||||
auto result = c1 ^^ c2;
|
||||
// exact result apparently depends on `real` precision => increased tolerance
|
||||
assert(isClose(result.re, -4.64705438e-17, 2e-4));
|
||||
assert(isClose(result.im, 2.52982e-1, 2e-4));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
assert(powmod(1U, 10U, 3U) == 1);
|
||||
assert(powmod(3U, 2U, 6U) == 3);
|
||||
assert(powmod(5U, 5U, 15U) == 5);
|
||||
assert(powmod(2U, 3U, 5U) == 3);
|
||||
assert(powmod(2U, 4U, 5U) == 1);
|
||||
assert(powmod(2U, 5U, 5U) == 2);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
import std.math.constants : E;
|
||||
|
||||
assert(exp(0.0) == 1.0);
|
||||
assert(exp(3.0).feqrel(E * E * E) > 16);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.traits : isIdentical;
|
||||
import std.math.operations : feqrel;
|
||||
|
||||
assert(isIdentical(expm1(0.0), 0.0));
|
||||
assert(expm1(1.0).feqrel(1.71828) > 16);
|
||||
assert(expm1(2.0).feqrel(6.3890) > 16);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.traits : isIdentical;
|
||||
import std.math.operations : feqrel;
|
||||
|
||||
assert(isIdentical(exp2(0.0), 1.0));
|
||||
assert(exp2(2.0).feqrel(4.0) > 16);
|
||||
assert(exp2(8.0).feqrel(256.0) > 16);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
int exp;
|
||||
real mantissa = frexp(123.456L, exp);
|
||||
|
||||
assert(isClose(mantissa * pow(2.0L, cast(real) exp), 123.456L));
|
||||
|
||||
assert(frexp(-real.nan, exp) && exp == int.min);
|
||||
assert(frexp(real.nan, exp) && exp == int.min);
|
||||
assert(frexp(-real.infinity, exp) == -real.infinity && exp == int.min);
|
||||
assert(frexp(real.infinity, exp) == real.infinity && exp == int.max);
|
||||
assert(frexp(-0.0, exp) == -0.0 && exp == 0);
|
||||
assert(frexp(0.0, exp) == 0.0 && exp == 0);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
assert(ilogb(1) == 0);
|
||||
assert(ilogb(3) == 1);
|
||||
assert(ilogb(3.0) == 1);
|
||||
assert(ilogb(100_000_000) == 26);
|
||||
|
||||
assert(ilogb(0) == FP_ILOGB0);
|
||||
assert(ilogb(0.0) == FP_ILOGB0);
|
||||
assert(ilogb(double.nan) == FP_ILOGBNAN);
|
||||
assert(ilogb(double.infinity) == int.max);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
assert(ilogb(0) == FP_ILOGB0);
|
||||
assert(ilogb(0.0) == FP_ILOGB0);
|
||||
assert(ilogb(double.nan) == FP_ILOGBNAN);
|
||||
}
|
||||
|
||||
@nogc @safe pure nothrow unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.meta : AliasSeq;
|
||||
static foreach (T; AliasSeq!(float, double, real))
|
||||
{{
|
||||
T r;
|
||||
|
||||
r = ldexp(3.0L, 3);
|
||||
assert(r == 24);
|
||||
|
||||
r = ldexp(cast(T) 3.0, cast(int) 3);
|
||||
assert(r == 24);
|
||||
|
||||
T n = 3.0;
|
||||
int exp = 3;
|
||||
r = ldexp(n, exp);
|
||||
assert(r == 24);
|
||||
}}
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
import std.math.constants : E;
|
||||
|
||||
assert(feqrel(log(E), 1) >= real.mant_dig - 1);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.algebraic : fabs;
|
||||
|
||||
assert(fabs(log10(1000.0L) - 3) < .000001);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.traits : isIdentical, isNaN;
|
||||
import std.math.operations : feqrel;
|
||||
|
||||
assert(isIdentical(log1p(0.0), 0.0));
|
||||
assert(log1p(1.0).feqrel(0.69314) > 16);
|
||||
|
||||
assert(log1p(-1.0) == -real.infinity);
|
||||
assert(isNaN(log1p(-2.0)));
|
||||
assert(log1p(real.nan) is real.nan);
|
||||
assert(log1p(-real.nan) is -real.nan);
|
||||
assert(log1p(real.infinity) == real.infinity);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
assert(isClose(log2(1024.0L), 10));
|
||||
}
|
||||
|
||||
@safe @nogc nothrow unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
assert(logb(1.0) == 0);
|
||||
assert(logb(100.0) == 6);
|
||||
|
||||
assert(logb(0.0) == -real.infinity);
|
||||
assert(logb(real.infinity) == real.infinity);
|
||||
assert(logb(-real.infinity) == real.infinity);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.exponential;
|
||||
|
||||
assert(scalbn(0x1.2345678abcdefp0L, 999) == 0x1.2345678abcdefp999L);
|
||||
assert(scalbn(-real.infinity, 5) == -real.infinity);
|
||||
assert(scalbn(2.0,10) == 2048.0);
|
||||
assert(scalbn(2048.0f,-10) == 2.0f);
|
||||
}
|
||||
|
18
libphobos/testsuite/libphobos.phobos/std_math_hardware.d
Normal file
18
libphobos/testsuite/libphobos.phobos/std_math_hardware.d
Normal file
|
@ -0,0 +1,18 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.math.hardware;
|
||||
|
||||
import std.math.rounding : lrint;
|
||||
|
||||
FloatingPointControl fpctrl;
|
||||
|
||||
fpctrl.rounding = FloatingPointControl.roundDown;
|
||||
assert(lrint(1.5) == 1.0);
|
||||
|
||||
fpctrl.rounding = FloatingPointControl.roundUp;
|
||||
assert(lrint(1.4) == 2.0);
|
||||
|
||||
fpctrl.rounding = FloatingPointControl.roundToNearest;
|
||||
assert(lrint(1.5) == 2.0);
|
||||
}
|
||||
|
217
libphobos/testsuite/libphobos.phobos/std_math_operations.d
Normal file
217
libphobos/testsuite/libphobos.phobos/std_math_operations.d
Normal file
|
@ -0,0 +1,217 @@
|
|||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
real a = NaN(1_000_000);
|
||||
assert(isNaN(a));
|
||||
assert(getNaNPayload(a) == 1_000_000);
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
real a = NaN(1_000_000);
|
||||
assert(isNaN(a));
|
||||
assert(getNaNPayload(a) == 1_000_000);
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert(nextUp(1.0 - 1.0e-6).feqrel(0.999999) > 16);
|
||||
assert(nextUp(1.0 - real.epsilon).feqrel(1.0) > 16);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert( nextDown(1.0 + real.epsilon) == 1.0);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
float a = 1;
|
||||
assert(is(typeof(nextafter(a, a)) == float));
|
||||
assert(nextafter(a, a.infinity) > a);
|
||||
assert(isNaN(nextafter(a, a.nan)));
|
||||
assert(isNaN(nextafter(a.nan, a)));
|
||||
|
||||
double b = 2;
|
||||
assert(is(typeof(nextafter(b, b)) == double));
|
||||
assert(nextafter(b, b.infinity) > b);
|
||||
assert(isNaN(nextafter(b, b.nan)));
|
||||
assert(isNaN(nextafter(b.nan, b)));
|
||||
|
||||
real c = 3;
|
||||
assert(is(typeof(nextafter(c, c)) == real));
|
||||
assert(nextafter(c, c.infinity) > c);
|
||||
assert(isNaN(nextafter(c, c.nan)));
|
||||
assert(isNaN(nextafter(c.nan, c)));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
assert(fdim(2.0, 0.0) == 2.0);
|
||||
assert(fdim(-2.0, 0.0) == 0.0);
|
||||
assert(fdim(real.infinity, 2.0) == real.infinity);
|
||||
assert(isNaN(fdim(real.nan, 2.0)));
|
||||
assert(isNaN(fdim(2.0, real.nan)));
|
||||
assert(isNaN(fdim(real.nan, real.nan)));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
import std.meta : AliasSeq;
|
||||
static foreach (F; AliasSeq!(float, double, real))
|
||||
{
|
||||
assert(fmax(F(0.0), F(2.0)) == 2.0);
|
||||
assert(fmax(F(-2.0), 0.0) == F(0.0));
|
||||
assert(fmax(F.infinity, F(2.0)) == F.infinity);
|
||||
assert(fmax(F.nan, F(2.0)) == F(2.0));
|
||||
assert(fmax(F(2.0), F.nan) == F(2.0));
|
||||
}
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
import std.meta : AliasSeq;
|
||||
static foreach (F; AliasSeq!(float, double, real))
|
||||
{
|
||||
assert(fmin(F(0.0), F(2.0)) == 0.0);
|
||||
assert(fmin(F(-2.0), F(0.0)) == -2.0);
|
||||
assert(fmin(F.infinity, F(2.0)) == 2.0);
|
||||
assert(fmin(F.nan, F(2.0)) == 2.0);
|
||||
assert(fmin(F(2.0), F.nan) == 2.0);
|
||||
}
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert(fma(0.0, 2.0, 2.0) == 2.0);
|
||||
assert(fma(2.0, 2.0, 2.0) == 6.0);
|
||||
assert(fma(real.infinity, 2.0, 2.0) == real.infinity);
|
||||
assert(fma(real.nan, 2.0, 2.0) is real.nan);
|
||||
assert(fma(2.0, 2.0, real.nan) is real.nan);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert(feqrel(2.0, 2.0) == 53);
|
||||
assert(feqrel(2.0f, 2.0f) == 24);
|
||||
assert(feqrel(2.0, double.nan) == 0);
|
||||
|
||||
// Test that numbers are within n digits of each
|
||||
// other by testing if feqrel > n * log2(10)
|
||||
|
||||
// five digits
|
||||
assert(feqrel(2.0, 2.00001) > 16);
|
||||
// ten digits
|
||||
assert(feqrel(2.0, 2.00000000001) > 33);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert(isClose(1.0,0.999_999_999));
|
||||
assert(isClose(0.001, 0.000_999_999_999));
|
||||
assert(isClose(1_000_000_000.0,999_999_999.0));
|
||||
|
||||
assert(isClose(17.123_456_789, 17.123_456_78));
|
||||
assert(!isClose(17.123_456_789, 17.123_45));
|
||||
|
||||
// use explicit 3rd parameter for less (or more) accuracy
|
||||
assert(isClose(17.123_456_789, 17.123_45, 1e-6));
|
||||
assert(!isClose(17.123_456_789, 17.123_45, 1e-7));
|
||||
|
||||
// use 4th parameter when comparing close to zero
|
||||
assert(!isClose(1e-100, 0.0));
|
||||
assert(isClose(1e-100, 0.0, 0.0, 1e-90));
|
||||
assert(!isClose(1e-10, -1e-10));
|
||||
assert(isClose(1e-10, -1e-10, 0.0, 1e-9));
|
||||
assert(!isClose(1e-300, 1e-298));
|
||||
assert(isClose(1e-300, 1e-298, 0.0, 1e-200));
|
||||
|
||||
// different default limits for different floating point types
|
||||
assert(isClose(1.0f, 0.999_99f));
|
||||
assert(!isClose(1.0, 0.999_99));
|
||||
static if (real.sizeof > double.sizeof)
|
||||
assert(!isClose(1.0L, 0.999_999_999L));
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert(isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001, 3.0]));
|
||||
assert(!isClose([1.0, 2.0], [0.999_999_999, 2.000_000_001, 3.0]));
|
||||
assert(!isClose([1.0, 2.0, 3.0], [0.999_999_999, 2.000_000_001]));
|
||||
|
||||
assert(isClose([2.0, 1.999_999_999, 2.000_000_001], 2.0));
|
||||
assert(isClose(2.0, [2.0, 1.999_999_999, 2.000_000_001]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert(cmp(-double.infinity, -double.max) < 0);
|
||||
assert(cmp(-double.max, -100.0) < 0);
|
||||
assert(cmp(-100.0, -0.5) < 0);
|
||||
assert(cmp(-0.5, 0.0) < 0);
|
||||
assert(cmp(0.0, 0.5) < 0);
|
||||
assert(cmp(0.5, 100.0) < 0);
|
||||
assert(cmp(100.0, double.max) < 0);
|
||||
assert(cmp(double.max, double.infinity) < 0);
|
||||
|
||||
assert(cmp(1.0, 1.0) == 0);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert(cmp(-0.0, +0.0) < 0);
|
||||
assert(cmp(+0.0, -0.0) > 0);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert(cmp(-double.nan, -double.infinity) < 0);
|
||||
assert(cmp(double.infinity, double.nan) < 0);
|
||||
assert(cmp(-double.nan, double.nan) < 0);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.operations;
|
||||
|
||||
assert(cmp(NaN(10), NaN(20)) < 0);
|
||||
assert(cmp(-NaN(20), -NaN(10)) < 0);
|
||||
}
|
||||
|
54
libphobos/testsuite/libphobos.phobos/std_math_remainder.d
Normal file
54
libphobos/testsuite/libphobos.phobos/std_math_remainder.d
Normal file
|
@ -0,0 +1,54 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.math.remainder;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
import std.math.traits : isIdentical, isNaN;
|
||||
|
||||
assert(isIdentical(fmod(0.0, 1.0), 0.0));
|
||||
assert(fmod(5.0, 3.0).feqrel(2.0) > 16);
|
||||
assert(isNaN(fmod(5.0, 0.0)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.remainder;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
|
||||
real frac;
|
||||
real intpart;
|
||||
|
||||
frac = modf(3.14159, intpart);
|
||||
assert(intpart.feqrel(3.0) > 16);
|
||||
assert(frac.feqrel(0.14159) > 16);
|
||||
}
|
||||
|
||||
@safe @nogc nothrow unittest
|
||||
{
|
||||
import std.math.remainder;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
assert(remainder(5.1, 3.0).feqrel(-0.9) > 16);
|
||||
assert(remainder(-5.1, 3.0).feqrel(0.9) > 16);
|
||||
assert(remainder(0.0, 3.0) == 0.0);
|
||||
|
||||
assert(isNaN(remainder(1.0, 0.0)));
|
||||
assert(isNaN(remainder(-1.0, 0.0)));
|
||||
}
|
||||
|
||||
@safe @nogc nothrow unittest
|
||||
{
|
||||
import std.math.remainder;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
|
||||
int n;
|
||||
|
||||
assert(remquo(5.1, 3.0, n).feqrel(-0.9) > 16 && n == 2);
|
||||
assert(remquo(-5.1, 3.0, n).feqrel(0.9) > 16 && n == -2);
|
||||
assert(remquo(0.0, 3.0, n) == 0.0 && n == 0);
|
||||
}
|
||||
|
171
libphobos/testsuite/libphobos.phobos/std_math_rounding.d
Normal file
171
libphobos/testsuite/libphobos.phobos/std_math_rounding.d
Normal file
|
@ -0,0 +1,171 @@
|
|||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
assert(ceil(+123.456L) == +124);
|
||||
assert(ceil(-123.456L) == -123);
|
||||
assert(ceil(-1.234L) == -1);
|
||||
assert(ceil(-0.123L) == 0);
|
||||
assert(ceil(0.0L) == 0);
|
||||
assert(ceil(+0.123L) == 1);
|
||||
assert(ceil(+1.234L) == 2);
|
||||
assert(ceil(real.infinity) == real.infinity);
|
||||
assert(isNaN(ceil(real.nan)));
|
||||
assert(isNaN(ceil(real.init)));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
assert(floor(+123.456L) == +123);
|
||||
assert(floor(-123.456L) == -124);
|
||||
assert(floor(+123.0L) == +123);
|
||||
assert(floor(-124.0L) == -124);
|
||||
assert(floor(-1.234L) == -2);
|
||||
assert(floor(-0.123L) == -1);
|
||||
assert(floor(0.0L) == 0);
|
||||
assert(floor(+0.123L) == 0);
|
||||
assert(floor(+1.234L) == 1);
|
||||
assert(floor(real.infinity) == real.infinity);
|
||||
assert(isNaN(floor(real.nan)));
|
||||
assert(isNaN(floor(real.init)));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
assert(isClose(12345.6789L.quantize(0.01L), 12345.68L));
|
||||
assert(isClose(12345.6789L.quantize!floor(0.01L), 12345.67L));
|
||||
assert(isClose(12345.6789L.quantize(22.0L), 12342.0L));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
assert(isClose(12345.6789L.quantize(0), 12345.6789L));
|
||||
assert(12345.6789L.quantize(real.infinity).isNaN);
|
||||
assert(12345.6789L.quantize(real.nan).isNaN);
|
||||
assert(real.infinity.quantize(0.01L) == real.infinity);
|
||||
assert(real.infinity.quantize(real.nan).isNaN);
|
||||
assert(real.nan.quantize(0.01L).isNaN);
|
||||
assert(real.nan.quantize(real.infinity).isNaN);
|
||||
assert(real.nan.quantize(real.nan).isNaN);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
assert(isClose(12345.6789L.quantize!10(-2), 12345.68L));
|
||||
assert(isClose(12345.6789L.quantize!(10, -2), 12345.68L));
|
||||
assert(isClose(12345.6789L.quantize!(10, floor)(-2), 12345.67L));
|
||||
assert(isClose(12345.6789L.quantize!(10, -2, floor), 12345.67L));
|
||||
|
||||
assert(isClose(12345.6789L.quantize!22(1), 12342.0L));
|
||||
assert(isClose(12345.6789L.quantize!22, 12342.0L));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
assert(nearbyint(0.4) == 0);
|
||||
assert(nearbyint(0.5) == 0);
|
||||
assert(nearbyint(0.6) == 1);
|
||||
assert(nearbyint(100.0) == 100);
|
||||
|
||||
assert(isNaN(nearbyint(real.nan)));
|
||||
assert(nearbyint(real.infinity) == real.infinity);
|
||||
assert(nearbyint(-real.infinity) == -real.infinity);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
version (IeeeFlagsSupport) resetIeeeFlags();
|
||||
assert(rint(0.4) == 0);
|
||||
version (GNU) { /* inexact bit not set with enabled optimizations */ } else
|
||||
version (IeeeFlagsSupport) assert(ieeeFlags.inexact);
|
||||
|
||||
assert(rint(0.5) == 0);
|
||||
assert(rint(0.6) == 1);
|
||||
assert(rint(100.0) == 100);
|
||||
|
||||
assert(isNaN(rint(real.nan)));
|
||||
assert(rint(real.infinity) == real.infinity);
|
||||
assert(rint(-real.infinity) == -real.infinity);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
assert(lrint(4.5) == 4);
|
||||
assert(lrint(5.5) == 6);
|
||||
assert(lrint(-4.5) == -4);
|
||||
assert(lrint(-5.5) == -6);
|
||||
|
||||
assert(lrint(int.max - 0.5) == 2147483646L);
|
||||
assert(lrint(int.max + 0.5) == 2147483648L);
|
||||
assert(lrint(int.min - 0.5) == -2147483648L);
|
||||
assert(lrint(int.min + 0.5) == -2147483648L);
|
||||
}
|
||||
|
||||
@safe nothrow @nogc unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
assert(round(4.5) == 5);
|
||||
assert(round(5.4) == 5);
|
||||
assert(round(-4.5) == -5);
|
||||
assert(round(-5.1) == -5);
|
||||
}
|
||||
|
||||
@safe nothrow @nogc unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
assert(lround(0.49) == 0);
|
||||
assert(lround(0.5) == 1);
|
||||
assert(lround(1.5) == 2);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
assert(trunc(0.01) == 0);
|
||||
assert(trunc(0.49) == 0);
|
||||
assert(trunc(0.5) == 0);
|
||||
assert(trunc(1.5) == 1);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.rounding;
|
||||
|
||||
assert(rndtol(1.0) == 1L);
|
||||
assert(rndtol(1.2) == 1L);
|
||||
assert(rndtol(1.7) == 2L);
|
||||
assert(rndtol(1.0001) == 1L);
|
||||
}
|
||||
|
189
libphobos/testsuite/libphobos.phobos/std_math_traits.d
Normal file
189
libphobos/testsuite/libphobos.phobos/std_math_traits.d
Normal file
|
@ -0,0 +1,189 @@
|
|||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
assert( isNaN(float.init));
|
||||
assert( isNaN(-double.init));
|
||||
assert( isNaN(real.nan));
|
||||
assert( isNaN(-real.nan));
|
||||
assert(!isNaN(cast(float) 53.6));
|
||||
assert(!isNaN(cast(real)-53.6));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
assert( isFinite(1.23f));
|
||||
assert( isFinite(float.max));
|
||||
assert( isFinite(float.min_normal));
|
||||
assert(!isFinite(float.nan));
|
||||
assert(!isFinite(float.infinity));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
float f = 3;
|
||||
double d = 500;
|
||||
real e = 10e+48;
|
||||
|
||||
assert(isNormal(f));
|
||||
assert(isNormal(d));
|
||||
assert(isNormal(e));
|
||||
f = d = e = 0;
|
||||
assert(!isNormal(f));
|
||||
assert(!isNormal(d));
|
||||
assert(!isNormal(e));
|
||||
assert(!isNormal(real.infinity));
|
||||
assert(isNormal(-real.max));
|
||||
assert(!isNormal(real.min_normal/4));
|
||||
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
import std.meta : AliasSeq;
|
||||
|
||||
static foreach (T; AliasSeq!(float, double, real))
|
||||
{{
|
||||
T f;
|
||||
for (f = 1.0; !isSubnormal(f); f /= 2)
|
||||
assert(f != 0);
|
||||
}}
|
||||
}
|
||||
|
||||
@nogc @safe pure nothrow unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
assert(!isInfinity(float.init));
|
||||
assert(!isInfinity(-float.init));
|
||||
assert(!isInfinity(float.nan));
|
||||
assert(!isInfinity(-float.nan));
|
||||
assert(isInfinity(float.infinity));
|
||||
assert(isInfinity(-float.infinity));
|
||||
assert(isInfinity(-1.0f / 0.0f));
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
// We're forcing the CTFE to run by assigning the result of the function to an enum
|
||||
enum test1 = isIdentical(1.0,1.0);
|
||||
enum test2 = isIdentical(real.nan,real.nan);
|
||||
enum test3 = isIdentical(real.infinity, real.infinity);
|
||||
enum test4 = isIdentical(real.infinity, real.infinity);
|
||||
enum test5 = isIdentical(0.0, 0.0);
|
||||
|
||||
assert(test1);
|
||||
assert(test2);
|
||||
assert(test3);
|
||||
assert(test4);
|
||||
assert(test5);
|
||||
|
||||
enum test6 = !isIdentical(0.0, -0.0);
|
||||
enum test7 = !isIdentical(real.nan, -real.nan);
|
||||
enum test8 = !isIdentical(real.infinity, -real.infinity);
|
||||
|
||||
assert(test6);
|
||||
assert(test7);
|
||||
assert(test8);
|
||||
}
|
||||
|
||||
@nogc @safe pure nothrow unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
assert(!signbit(float.nan));
|
||||
assert(signbit(-float.nan));
|
||||
assert(!signbit(168.1234f));
|
||||
assert(signbit(-168.1234f));
|
||||
assert(!signbit(0.0f));
|
||||
assert(signbit(-0.0f));
|
||||
assert(signbit(-float.max));
|
||||
assert(!signbit(float.max));
|
||||
|
||||
assert(!signbit(double.nan));
|
||||
assert(signbit(-double.nan));
|
||||
assert(!signbit(168.1234));
|
||||
assert(signbit(-168.1234));
|
||||
assert(!signbit(0.0));
|
||||
assert(signbit(-0.0));
|
||||
assert(signbit(-double.max));
|
||||
assert(!signbit(double.max));
|
||||
|
||||
assert(!signbit(real.nan));
|
||||
assert(signbit(-real.nan));
|
||||
assert(!signbit(168.1234L));
|
||||
assert(signbit(-168.1234L));
|
||||
assert(!signbit(0.0L));
|
||||
assert(signbit(-0.0L));
|
||||
assert(signbit(-real.max));
|
||||
assert(!signbit(real.max));
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
assert(copysign(1.0, 1.0) == 1.0);
|
||||
assert(copysign(1.0, -0.0) == -1.0);
|
||||
assert(copysign(1UL, -1.0) == -1.0);
|
||||
assert(copysign(-1.0, -1.0) == -1.0);
|
||||
|
||||
assert(copysign(real.infinity, -1.0) == -real.infinity);
|
||||
assert(copysign(real.nan, 1.0) is real.nan);
|
||||
assert(copysign(-real.nan, 1.0) is real.nan);
|
||||
assert(copysign(real.nan, -1.0) is -real.nan);
|
||||
}
|
||||
|
||||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
assert(sgn(168.1234) == 1);
|
||||
assert(sgn(-168.1234) == -1);
|
||||
assert(sgn(0.0) == 0);
|
||||
assert(sgn(-0.0) == 0);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
import std.math.exponential : pow;
|
||||
|
||||
assert( isPowerOf2(1.0L));
|
||||
assert( isPowerOf2(2.0L));
|
||||
assert( isPowerOf2(0.5L));
|
||||
assert( isPowerOf2(pow(2.0L, 96)));
|
||||
assert( isPowerOf2(pow(2.0L, -77)));
|
||||
|
||||
assert(!isPowerOf2(-2.0L));
|
||||
assert(!isPowerOf2(-0.5L));
|
||||
assert(!isPowerOf2(0.0L));
|
||||
assert(!isPowerOf2(4.315));
|
||||
assert(!isPowerOf2(1.0L / 3.0L));
|
||||
|
||||
assert(!isPowerOf2(real.nan));
|
||||
assert(!isPowerOf2(real.infinity));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.traits;
|
||||
|
||||
assert( isPowerOf2(1));
|
||||
assert( isPowerOf2(2));
|
||||
assert( isPowerOf2(1uL << 63));
|
||||
|
||||
assert(!isPowerOf2(-4));
|
||||
assert(!isPowerOf2(0));
|
||||
assert(!isPowerOf2(1337u));
|
||||
}
|
||||
|
168
libphobos/testsuite/libphobos.phobos/std_math_trigonometry.d
Normal file
168
libphobos/testsuite/libphobos.phobos/std_math_trigonometry.d
Normal file
|
@ -0,0 +1,168 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
assert(cos(0.0) == 1.0);
|
||||
assert(cos(1.0).isClose(0.5403023059));
|
||||
assert(cos(3.0).isClose(-0.9899924966));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.constants : PI;
|
||||
import std.stdio : writefln;
|
||||
|
||||
void someFunc()
|
||||
{
|
||||
real x = 30.0;
|
||||
auto result = sin(x * (PI / 180)); // convert degrees to radians
|
||||
writefln("The sine of %s degrees is %s", x, result);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.traits : isIdentical;
|
||||
import std.math.constants : PI;
|
||||
import std.math.algebraic : sqrt;
|
||||
|
||||
assert(isIdentical(tan(0.0), 0.0));
|
||||
assert(tan(PI).isClose(0, 0.0, 1e-10));
|
||||
assert(tan(PI / 3).isClose(sqrt(3.0)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.traits : isNaN;
|
||||
import std.math.constants : PI;
|
||||
|
||||
assert(acos(0.0).isClose(1.570796327));
|
||||
assert(acos(0.5).isClose(PI / 3));
|
||||
assert(acos(PI).isNaN);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.traits : isIdentical, isNaN;
|
||||
import std.math.constants : PI;
|
||||
|
||||
assert(isIdentical(asin(0.0), 0.0));
|
||||
assert(asin(0.5).isClose(PI / 6));
|
||||
assert(asin(PI).isNaN);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.traits : isIdentical;
|
||||
import std.math.constants : PI;
|
||||
import std.math.algebraic : sqrt;
|
||||
|
||||
assert(isIdentical(atan(0.0), 0.0));
|
||||
assert(atan(sqrt(3.0)).isClose(PI / 3));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.constants : PI;
|
||||
import std.math.algebraic : sqrt;
|
||||
|
||||
assert(atan2(1.0, sqrt(3.0)).isClose(PI / 6));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.constants : E;
|
||||
import std.math.operations : isClose;
|
||||
|
||||
assert(cosh(0.0) == 1.0);
|
||||
assert(cosh(1.0).isClose((E + 1.0 / E) / 2));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.constants : E;
|
||||
import std.math.operations : isClose;
|
||||
import std.math.traits : isIdentical;
|
||||
|
||||
enum sinh1 = (E - 1.0 / E) / 2;
|
||||
import std.meta : AliasSeq;
|
||||
static foreach (F; AliasSeq!(float, double, real))
|
||||
{
|
||||
assert(isIdentical(sinh(F(0.0)), F(0.0)));
|
||||
assert(sinh(F(1.0)).isClose(F(sinh1)));
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.traits : isIdentical;
|
||||
|
||||
assert(isIdentical(tanh(0.0), 0.0));
|
||||
assert(tanh(1.0).isClose(sinh(1.0) / cosh(1.0)));
|
||||
}
|
||||
|
||||
@safe @nogc nothrow unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.traits : isIdentical, isNaN;
|
||||
|
||||
assert(isNaN(acosh(0.9)));
|
||||
assert(isNaN(acosh(real.nan)));
|
||||
assert(isIdentical(acosh(1.0), 0.0));
|
||||
assert(acosh(real.infinity) == real.infinity);
|
||||
assert(isNaN(acosh(0.5)));
|
||||
}
|
||||
|
||||
@safe @nogc nothrow unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.traits : isIdentical, isNaN;
|
||||
|
||||
assert(isIdentical(asinh(0.0), 0.0));
|
||||
assert(isIdentical(asinh(-0.0), -0.0));
|
||||
assert(asinh(real.infinity) == real.infinity);
|
||||
assert(asinh(-real.infinity) == -real.infinity);
|
||||
assert(isNaN(asinh(real.nan)));
|
||||
}
|
||||
|
||||
@safe @nogc nothrow unittest
|
||||
{
|
||||
import std.math.trigonometry;
|
||||
|
||||
import std.math.traits : isIdentical, isNaN;
|
||||
|
||||
assert(isIdentical(atanh(0.0), 0.0));
|
||||
assert(isIdentical(atanh(-0.0),-0.0));
|
||||
assert(isNaN(atanh(real.nan)));
|
||||
assert(isNaN(atanh(-real.infinity)));
|
||||
assert(atanh(0.0) == 0);
|
||||
}
|
||||
|
525
libphobos/testsuite/libphobos.phobos/std_meta.d
Normal file
525
libphobos/testsuite/libphobos.phobos/std_meta.d
Normal file
|
@ -0,0 +1,525 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.meta;
|
||||
alias TL = AliasSeq!(int, double);
|
||||
|
||||
int foo(TL td) // same as int foo(int, double);
|
||||
{
|
||||
return td[0] + cast(int) td[1];
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias TL = AliasSeq!(int, double);
|
||||
|
||||
alias Types = AliasSeq!(TL, char);
|
||||
static assert(is(Types == AliasSeq!(int, double, char)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
// Creates a compile-time sequence of function call expressions
|
||||
// that each call `func` with the next variadic template argument
|
||||
template Map(alias func, args...)
|
||||
{
|
||||
auto ref lazyItem() {return func(args[0]);}
|
||||
|
||||
static if (args.length == 1)
|
||||
{
|
||||
alias Map = lazyItem;
|
||||
}
|
||||
else
|
||||
{
|
||||
// recurse
|
||||
alias Map = AliasSeq!(lazyItem, Map!(func, args[1 .. $]));
|
||||
}
|
||||
}
|
||||
|
||||
static void test(int a, int b)
|
||||
{
|
||||
assert(a == 4);
|
||||
assert(b == 16);
|
||||
}
|
||||
|
||||
static int a = 2;
|
||||
static int b = 4;
|
||||
|
||||
test(Map!(i => i ^^ 2, a, b));
|
||||
assert(a == 2);
|
||||
assert(b == 4);
|
||||
|
||||
test(Map!((ref i) => i *= i, a, b));
|
||||
assert(a == 4);
|
||||
assert(b == 16);
|
||||
|
||||
static void testRef(ref int a, ref int b)
|
||||
{
|
||||
assert(a++ == 16);
|
||||
assert(b++ == 256);
|
||||
}
|
||||
|
||||
testRef(Map!(function ref(ref i) => i *= i, a, b));
|
||||
assert(a == 17);
|
||||
assert(b == 257);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
// Without Alias this would fail if Args[0] was e.g. a value and
|
||||
// some logic would be needed to detect when to use enum instead
|
||||
alias Head(Args...) = Alias!(Args[0]);
|
||||
alias Tail(Args...) = Args[1 .. $];
|
||||
|
||||
alias Blah = AliasSeq!(3, int, "hello");
|
||||
static assert(Head!Blah == 3);
|
||||
static assert(is(Head!(Tail!Blah) == int));
|
||||
static assert((Tail!Blah)[1] == "hello");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias a = Alias!(123);
|
||||
static assert(a == 123);
|
||||
|
||||
enum abc = 1;
|
||||
alias b = Alias!(abc);
|
||||
static assert(b == 1);
|
||||
|
||||
alias c = Alias!(3 + 4);
|
||||
static assert(c == 7);
|
||||
|
||||
alias concat = (s0, s1) => s0 ~ s1;
|
||||
alias d = Alias!(concat("Hello", " World!"));
|
||||
static assert(d == "Hello World!");
|
||||
|
||||
alias e = Alias!(int);
|
||||
static assert(is(e == int));
|
||||
|
||||
alias f = Alias!(AliasSeq!(int));
|
||||
static assert(!is(typeof(f[0]))); //not an AliasSeq
|
||||
static assert(is(f == int));
|
||||
|
||||
auto g = 6;
|
||||
alias h = Alias!g;
|
||||
++h;
|
||||
assert(g == 7);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.stdio;
|
||||
|
||||
void foo()
|
||||
{
|
||||
writefln("The index of long is %s",
|
||||
staticIndexOf!(long, AliasSeq!(int, long, double)));
|
||||
// prints: The index of long is 1
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias Types = AliasSeq!(int, long, double, char);
|
||||
alias TL = Erase!(long, Types);
|
||||
static assert(is(TL == AliasSeq!(int, double, char)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias Types = AliasSeq!(int, long, long, int);
|
||||
static assert(is(EraseAll!(long, Types) == AliasSeq!(int, int)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias Types = AliasSeq!(int, long, long, int, float);
|
||||
|
||||
alias TL = NoDuplicates!(Types);
|
||||
static assert(is(TL == AliasSeq!(int, long, float)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias Types = AliasSeq!(int, long, long, int, float);
|
||||
|
||||
alias TL = Replace!(long, char, Types);
|
||||
static assert(is(TL == AliasSeq!(int, char, long, int, float)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias Types = AliasSeq!(int, long, long, int, float);
|
||||
|
||||
alias TL = ReplaceAll!(long, char, Types);
|
||||
static assert(is(TL == AliasSeq!(int, char, char, int, float)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias Types = AliasSeq!(int, long, long, int, float, byte, ubyte, short, ushort, uint);
|
||||
|
||||
alias TL = Reverse!(Types);
|
||||
static assert(is(TL == AliasSeq!(uint, ushort, short, ubyte, byte, float, int, long, long, int)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
class A { }
|
||||
class B : A { }
|
||||
class C : B { }
|
||||
alias Types = AliasSeq!(A, C, B);
|
||||
|
||||
MostDerived!(Object, Types) x; // x is declared as type C
|
||||
static assert(is(typeof(x) == C));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
class A { }
|
||||
class B : A { }
|
||||
class C : B { }
|
||||
alias Types = AliasSeq!(A, C, B);
|
||||
|
||||
alias TL = DerivedToFront!(Types);
|
||||
static assert(is(TL == AliasSeq!(C, B, A)));
|
||||
|
||||
alias TL2 = DerivedToFront!(A, A, A, B, B, B, C, C, C);
|
||||
static assert(is(TL2 == AliasSeq!(C, C, C, B, B, B, A, A, A)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : Unqual;
|
||||
alias TL = staticMap!(Unqual, int, const int, immutable int, uint, ubyte, byte, short, ushort);
|
||||
static assert(is(TL == AliasSeq!(int, int, int, uint, ubyte, byte, short, ushort)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : isIntegral;
|
||||
|
||||
static assert(!allSatisfy!(isIntegral, int, double));
|
||||
static assert( allSatisfy!(isIntegral, int, long));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : isIntegral;
|
||||
|
||||
static assert(!anySatisfy!(isIntegral, string, double));
|
||||
static assert( anySatisfy!(isIntegral, int, double));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : isNarrowString, isUnsigned;
|
||||
|
||||
alias Types1 = AliasSeq!(string, wstring, dchar[], char[], dstring, int);
|
||||
alias TL1 = Filter!(isNarrowString, Types1);
|
||||
static assert(is(TL1 == AliasSeq!(string, wstring, char[])));
|
||||
|
||||
alias Types2 = AliasSeq!(int, byte, ubyte, dstring, dchar, uint, ulong);
|
||||
alias TL2 = Filter!(isUnsigned, Types2);
|
||||
static assert(is(TL2 == AliasSeq!(ubyte, uint, ulong)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : isPointer;
|
||||
|
||||
alias isNoPointer = templateNot!isPointer;
|
||||
static assert(!isNoPointer!(int*));
|
||||
static assert(allSatisfy!(isNoPointer, string, char, float));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : isNumeric, isUnsigned;
|
||||
|
||||
alias storesNegativeNumbers = templateAnd!(isNumeric, templateNot!isUnsigned);
|
||||
static assert(storesNegativeNumbers!int);
|
||||
static assert(!storesNegativeNumbers!string && !storesNegativeNumbers!uint);
|
||||
|
||||
// An empty sequence of predicates always yields true.
|
||||
alias alwaysTrue = templateAnd!();
|
||||
static assert(alwaysTrue!int);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : isPointer, isUnsigned;
|
||||
|
||||
alias isPtrOrUnsigned = templateOr!(isPointer, isUnsigned);
|
||||
static assert( isPtrOrUnsigned!uint && isPtrOrUnsigned!(short*));
|
||||
static assert(!isPtrOrUnsigned!int && !isPtrOrUnsigned!(string));
|
||||
|
||||
// An empty sequence of predicates never yields true.
|
||||
alias alwaysFalse = templateOr!();
|
||||
static assert(!alwaysFalse!int);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.algorithm.iteration : map;
|
||||
import std.algorithm.sorting : sort;
|
||||
import std.string : capitalize;
|
||||
|
||||
struct S
|
||||
{
|
||||
int a;
|
||||
int c;
|
||||
int b;
|
||||
}
|
||||
|
||||
alias capMembers = aliasSeqOf!([__traits(allMembers, S)].sort().map!capitalize());
|
||||
static assert(capMembers[0] == "A");
|
||||
static assert(capMembers[1] == "B");
|
||||
static assert(capMembers[2] == "C");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
static immutable REF = [0, 1, 2, 3];
|
||||
foreach (I, V; aliasSeqOf!([0, 1, 2, 3]))
|
||||
{
|
||||
static assert(V == I);
|
||||
static assert(V == REF[I]);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
// enum bool isImplicitlyConvertible(From, To)
|
||||
import std.traits : isImplicitlyConvertible;
|
||||
|
||||
static assert(allSatisfy!(
|
||||
ApplyLeft!(isImplicitlyConvertible, ubyte),
|
||||
short, ushort, int, uint, long, ulong));
|
||||
|
||||
static assert(is(Filter!(ApplyRight!(isImplicitlyConvertible, short),
|
||||
ubyte, string, short, float, int) == AliasSeq!(ubyte, short)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : hasMember, ifTestable;
|
||||
|
||||
struct T1
|
||||
{
|
||||
bool foo;
|
||||
}
|
||||
|
||||
struct T2
|
||||
{
|
||||
struct Test
|
||||
{
|
||||
bool opCast(T : bool)() { return true; }
|
||||
}
|
||||
|
||||
Test foo;
|
||||
}
|
||||
|
||||
static assert(allSatisfy!(ApplyRight!(hasMember, "foo"), T1, T2));
|
||||
static assert(allSatisfy!(ApplyRight!(ifTestable, a => a.foo), T1, T2));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : Largest;
|
||||
|
||||
alias Types = AliasSeq!(byte, short, int, long);
|
||||
|
||||
static assert(is(staticMap!(ApplyLeft!(Largest, short), Types) ==
|
||||
AliasSeq!(short, short, int, long)));
|
||||
static assert(is(staticMap!(ApplyLeft!(Largest, int), Types) ==
|
||||
AliasSeq!(int, int, int, long)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
import std.traits : FunctionAttribute, SetFunctionAttributes;
|
||||
|
||||
static void foo() @system;
|
||||
static int bar(int) @system;
|
||||
|
||||
alias SafeFunctions = AliasSeq!(
|
||||
void function() @safe,
|
||||
int function(int) @safe);
|
||||
|
||||
static assert(is(staticMap!(ApplyRight!(
|
||||
SetFunctionAttributes, "D", FunctionAttribute.safe),
|
||||
typeof(&foo), typeof(&bar)) == SafeFunctions));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias ImInt0 = Repeat!(0, int);
|
||||
static assert(is(ImInt0 == AliasSeq!()));
|
||||
|
||||
alias ImInt1 = Repeat!(1, immutable(int));
|
||||
static assert(is(ImInt1 == AliasSeq!(immutable(int))));
|
||||
|
||||
alias Real3 = Repeat!(3, real);
|
||||
static assert(is(Real3 == AliasSeq!(real, real, real)));
|
||||
|
||||
alias Real12 = Repeat!(4, Real3);
|
||||
static assert(is(Real12 == AliasSeq!(real, real, real, real, real, real,
|
||||
real, real, real, real, real, real)));
|
||||
|
||||
alias Composite = AliasSeq!(uint, int);
|
||||
alias Composite2 = Repeat!(2, Composite);
|
||||
static assert(is(Composite2 == AliasSeq!(uint, int, uint, int)));
|
||||
|
||||
alias ImInt10 = Repeat!(10, int);
|
||||
static assert(is(ImInt10 == AliasSeq!(int, int, int, int, int, int, int, int, int, int)));
|
||||
|
||||
alias Big = Repeat!(1_000_000, int);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
auto staticArray(T, size_t n)(Repeat!(n, T) elems)
|
||||
{
|
||||
T[n] a = [elems];
|
||||
return a;
|
||||
}
|
||||
|
||||
auto a = staticArray!(long, 3)(3, 1, 4);
|
||||
assert(is(typeof(a) == long[3]));
|
||||
assert(a == [3, 1, 4]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias Nums = AliasSeq!(7, 2, 3, 23);
|
||||
enum Comp(int N1, int N2) = N1 < N2;
|
||||
static assert(AliasSeq!(2, 3, 7, 23) == staticSort!(Comp, Nums));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
alias Types = AliasSeq!(uint, short, ubyte, long, ulong);
|
||||
enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1);
|
||||
static assert(is(AliasSeq!(uint, ubyte, ulong, short, long) == staticSort!(Comp,
|
||||
Types)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
enum Comp(int N1, int N2) = N1 < N2;
|
||||
static assert( staticIsSorted!(Comp, 2, 2));
|
||||
static assert( staticIsSorted!(Comp, 2, 3, 7, 23));
|
||||
static assert(!staticIsSorted!(Comp, 7, 2, 3, 23));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
enum Comp(T1, T2) = __traits(isUnsigned, T2) - __traits(isUnsigned, T1);
|
||||
static assert( staticIsSorted!(Comp, uint, ubyte, ulong, short, long));
|
||||
static assert(!staticIsSorted!(Comp, uint, short, ubyte, long, ulong));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
static assert(is(Stride!(1, short, int, long) == AliasSeq!(short, int, long)));
|
||||
static assert(is(Stride!(2, short, int, long) == AliasSeq!(short, long)));
|
||||
static assert(is(Stride!(-1, short, int, long) == AliasSeq!(long, int, short)));
|
||||
static assert(is(Stride!(-2, short, int, long) == AliasSeq!(long, short)));
|
||||
|
||||
alias attribs = AliasSeq!(short, int, long, ushort, uint, ulong);
|
||||
static assert(is(Stride!(3, attribs) == AliasSeq!(short, ushort)));
|
||||
static assert(is(Stride!(3, attribs[1 .. $]) == AliasSeq!(int, uint)));
|
||||
static assert(is(Stride!(-3, attribs) == AliasSeq!(ulong, long)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.meta;
|
||||
|
||||
// ApplyRight combined with Instantiate can be used to apply various
|
||||
// templates to the same parameters.
|
||||
import std.string : leftJustify, center, rightJustify;
|
||||
alias functions = staticMap!(ApplyRight!(Instantiate, string),
|
||||
leftJustify, center, rightJustify);
|
||||
string result = "";
|
||||
static foreach (f; functions)
|
||||
{
|
||||
{
|
||||
auto x = &f; // not a template, but a function instantiation
|
||||
result ~= x("hello", 7);
|
||||
result ~= ";";
|
||||
}
|
||||
}
|
||||
|
||||
assert(result == "hello ; hello ; hello;");
|
||||
}
|
||||
|
43
libphobos/testsuite/libphobos.phobos/std_mmfile.d
Normal file
43
libphobos/testsuite/libphobos.phobos/std_mmfile.d
Normal file
|
@ -0,0 +1,43 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.mmfile;
|
||||
|
||||
import std.file;
|
||||
std.file.write(deleteme, "hello"); // deleteme is a temporary filename
|
||||
scope(exit) remove(deleteme);
|
||||
|
||||
// Use a scope class so the file will be closed at the end of this function
|
||||
scope mmfile = new MmFile(deleteme);
|
||||
|
||||
assert(mmfile.length == "hello".length);
|
||||
|
||||
// Access file contents with the slice operator
|
||||
// This is typed as `void[]`, so cast to `char[]` or `ubyte[]` to use it
|
||||
const data = cast(const(char)[]) mmfile[];
|
||||
|
||||
// At this point, the file content may not have been read yet.
|
||||
// In that case, the following memory access will intentionally
|
||||
// trigger a page fault, causing the kernel to load the file contents
|
||||
assert(data[0 .. 5] == "hello");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.mmfile;
|
||||
|
||||
import std.file;
|
||||
scope(exit) remove(deleteme);
|
||||
|
||||
scope mmfile = new MmFile(deleteme, MmFile.Mode.readWriteNew, 5, null);
|
||||
assert(mmfile.length == 5);
|
||||
|
||||
auto data = cast(ubyte[]) mmfile[];
|
||||
|
||||
// This write to memory will be reflected in the file contents
|
||||
data[] = '\n';
|
||||
|
||||
mmfile.flush();
|
||||
|
||||
assert(std.file.read(deleteme) == "\n\n\n\n\n");
|
||||
}
|
||||
|
203
libphobos/testsuite/libphobos.phobos/std_numeric.d
Normal file
203
libphobos/testsuite/libphobos.phobos/std_numeric.d
Normal file
|
@ -0,0 +1,203 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
import std.math.trigonometry : sin, cos;
|
||||
|
||||
// Define a 16-bit floating point values
|
||||
CustomFloat!16 x; // Using the number of bits
|
||||
CustomFloat!(10, 5) y; // Using the precision and exponent width
|
||||
CustomFloat!(10, 5,CustomFloatFlags.ieee) z; // Using the precision, exponent width and format flags
|
||||
CustomFloat!(10, 5,CustomFloatFlags.ieee, 15) w; // Using the precision, exponent width, format flags and exponent offset bias
|
||||
|
||||
// Use the 16-bit floats mostly like normal numbers
|
||||
w = x*y - 1;
|
||||
|
||||
// Functions calls require conversion
|
||||
z = sin(+x) + cos(+y); // Use unary plus to concisely convert to a real
|
||||
z = sin(x.get!float) + cos(y.get!float); // Or use get!T
|
||||
z = sin(cast(float) x) + cos(cast(float) y); // Or use cast(T) to explicitly convert
|
||||
|
||||
// Define a 8-bit custom float for storing probabilities
|
||||
alias Probability = CustomFloat!(4, 4, CustomFloatFlags.ieee^CustomFloatFlags.probability^CustomFloatFlags.signed );
|
||||
auto p = Probability(0.5);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
// Average numbers in an array
|
||||
double avg(in double[] a)
|
||||
{
|
||||
if (a.length == 0) return 0;
|
||||
FPTemporary!double result = 0;
|
||||
foreach (e; a) result += e;
|
||||
return result / a.length;
|
||||
}
|
||||
|
||||
auto a = [1.0, 2.0, 3.0];
|
||||
assert(isClose(avg(a), 2));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.trigonometry : cos;
|
||||
|
||||
float f(float x)
|
||||
{
|
||||
return cos(x) - x*x*x;
|
||||
}
|
||||
auto x = secantMethod!(f)(0f, 1f);
|
||||
assert(isClose(x, 0.865474));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
auto ret = findLocalMin((double x) => (x-4)^^2, -1e7, 1e7);
|
||||
assert(ret.x.isClose(4.0));
|
||||
assert(ret.y.isClose(0.0, 0.0, 1e-10));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
double[] a = [];
|
||||
assert(!normalize(a));
|
||||
a = [ 1.0, 3.0 ];
|
||||
assert(normalize(a));
|
||||
assert(a == [ 0.25, 0.75 ]);
|
||||
assert(normalize!(typeof(a))(a, 50)); // a = [12.5, 37.5]
|
||||
a = [ 0.0, 0.0 ];
|
||||
assert(!normalize(a));
|
||||
assert(a == [ 0.5, 0.5 ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
import std.math.traits : isNaN;
|
||||
|
||||
assert(sumOfLog2s(new double[0]) == 0);
|
||||
assert(sumOfLog2s([0.0L]) == -real.infinity);
|
||||
assert(sumOfLog2s([-0.0L]) == -real.infinity);
|
||||
assert(sumOfLog2s([2.0L]) == 1);
|
||||
assert(sumOfLog2s([-2.0L]).isNaN());
|
||||
assert(sumOfLog2s([real.nan]).isNaN());
|
||||
assert(sumOfLog2s([-real.nan]).isNaN());
|
||||
assert(sumOfLog2s([real.infinity]) == real.infinity);
|
||||
assert(sumOfLog2s([-real.infinity]).isNaN());
|
||||
assert(sumOfLog2s([ 0.25, 0.25, 0.25, 0.125 ]) == -9);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
double[] p = [ 0.0, 0, 0, 1 ];
|
||||
assert(kullbackLeiblerDivergence(p, p) == 0);
|
||||
double[] p1 = [ 0.25, 0.25, 0.25, 0.25 ];
|
||||
assert(kullbackLeiblerDivergence(p1, p1) == 0);
|
||||
assert(kullbackLeiblerDivergence(p, p1) == 2);
|
||||
assert(kullbackLeiblerDivergence(p1, p) == double.infinity);
|
||||
double[] p2 = [ 0.2, 0.2, 0.2, 0.4 ];
|
||||
assert(isClose(kullbackLeiblerDivergence(p1, p2), 0.0719281, 1e-5));
|
||||
assert(isClose(kullbackLeiblerDivergence(p2, p1), 0.0780719, 1e-5));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
double[] p = [ 0.0, 0, 0, 1 ];
|
||||
assert(jensenShannonDivergence(p, p) == 0);
|
||||
double[] p1 = [ 0.25, 0.25, 0.25, 0.25 ];
|
||||
assert(jensenShannonDivergence(p1, p1) == 0);
|
||||
assert(isClose(jensenShannonDivergence(p1, p), 0.548795, 1e-5));
|
||||
double[] p2 = [ 0.2, 0.2, 0.2, 0.4 ];
|
||||
assert(isClose(jensenShannonDivergence(p1, p2), 0.0186218, 1e-5));
|
||||
assert(isClose(jensenShannonDivergence(p2, p1), 0.0186218, 1e-5));
|
||||
assert(isClose(jensenShannonDivergence(p2, p1, 0.005), 0.00602366, 1e-5));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
import std.math.algebraic : sqrt;
|
||||
|
||||
string[] s = ["Hello", "brave", "new", "world"];
|
||||
string[] t = ["Hello", "new", "world"];
|
||||
assert(gapWeightedSimilarity(s, s, 1) == 15);
|
||||
assert(gapWeightedSimilarity(t, t, 1) == 7);
|
||||
assert(gapWeightedSimilarity(s, t, 1) == 7);
|
||||
assert(isClose(gapWeightedSimilarityNormalized(s, t, 1),
|
||||
7.0 / sqrt(15.0 * 7), 0.01));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
string[] s = ["Hello", "brave", "new", "world"];
|
||||
string[] t = ["Hello", "new", "world"];
|
||||
auto simIter = gapWeightedSimilarityIncremental(s, t, 1.0);
|
||||
assert(simIter.front == 3); // three 1-length matches
|
||||
simIter.popFront();
|
||||
assert(simIter.front == 3); // three 2-length matches
|
||||
simIter.popFront();
|
||||
assert(simIter.front == 1); // one 3-length match
|
||||
simIter.popFront();
|
||||
assert(simIter.empty); // no more match
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
assert(gcd(2 * 5 * 7 * 7, 5 * 7 * 11) == 5 * 7);
|
||||
const int a = 5 * 13 * 23 * 23, b = 13 * 59;
|
||||
assert(gcd(a, b) == 13);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
assert(lcm(1, 2) == 2);
|
||||
assert(lcm(3, 4) == 12);
|
||||
assert(lcm(5, 6) == 30);
|
||||
}
|
||||
|
||||
@safe pure @nogc unittest
|
||||
{
|
||||
import std.numeric;
|
||||
|
||||
ubyte[21] fac;
|
||||
size_t idx = decimalToFactorial(2982, fac);
|
||||
|
||||
assert(fac[0] == 4);
|
||||
assert(fac[1] == 0);
|
||||
assert(fac[2] == 4);
|
||||
assert(fac[3] == 1);
|
||||
assert(fac[4] == 0);
|
||||
assert(fac[5] == 0);
|
||||
assert(fac[6] == 0);
|
||||
}
|
||||
|
95
libphobos/testsuite/libphobos.phobos/std_outbuffer.d
Normal file
95
libphobos/testsuite/libphobos.phobos/std_outbuffer.d
Normal file
|
@ -0,0 +1,95 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.outbuffer;
|
||||
|
||||
OutBuffer buf = new OutBuffer();
|
||||
buf.write(cast(ubyte) 1);
|
||||
buf.align2();
|
||||
assert(buf.toBytes() == "\x01\x00");
|
||||
buf.write(cast(ubyte) 2);
|
||||
buf.align4();
|
||||
assert(buf.toBytes() == "\x01\x00\x02\x00");
|
||||
buf.write(cast(ubyte) 3);
|
||||
buf.alignSize(8);
|
||||
assert(buf.toBytes() == "\x01\x00\x02\x00\x03\x00\x00\x00");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.outbuffer;
|
||||
|
||||
OutBuffer buf = new OutBuffer();
|
||||
buf.write(cast(ubyte) 1);
|
||||
buf.align2(0x55);
|
||||
assert(buf.toBytes() == "\x01\x55");
|
||||
buf.write(cast(ubyte) 2);
|
||||
buf.align4(0x55);
|
||||
assert(buf.toBytes() == "\x01\x55\x02\x55");
|
||||
buf.write(cast(ubyte) 3);
|
||||
buf.alignSize(8, 0x55);
|
||||
assert(buf.toBytes() == "\x01\x55\x02\x55\x03\x55\x55\x55");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.outbuffer;
|
||||
|
||||
OutBuffer b = new OutBuffer();
|
||||
b.writef("a%sb", 16);
|
||||
assert(b.toString() == "a16b");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.outbuffer;
|
||||
|
||||
OutBuffer b = new OutBuffer();
|
||||
b.writef!"a%sb"(16);
|
||||
assert(b.toString() == "a16b");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.outbuffer;
|
||||
|
||||
OutBuffer b = new OutBuffer();
|
||||
b.writefln("a%sb", 16);
|
||||
assert(b.toString() == "a16b\n");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.outbuffer;
|
||||
|
||||
OutBuffer b = new OutBuffer();
|
||||
b.writefln!"a%sb"(16);
|
||||
assert(b.toString() == "a16b\n");
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.outbuffer;
|
||||
|
||||
import std.string : cmp;
|
||||
|
||||
OutBuffer buf = new OutBuffer();
|
||||
|
||||
assert(buf.offset == 0);
|
||||
buf.write("hello");
|
||||
buf.write(cast(byte) 0x20);
|
||||
buf.write("world");
|
||||
buf.writef(" %d", 62665);
|
||||
assert(cmp(buf.toString(), "hello world 62665") == 0);
|
||||
|
||||
buf.clear();
|
||||
assert(cmp(buf.toString(), "") == 0);
|
||||
buf.write("New data");
|
||||
assert(cmp(buf.toString(),"New data") == 0);
|
||||
}
|
||||
|
27
libphobos/testsuite/libphobos.phobos/std_package.d
Normal file
27
libphobos/testsuite/libphobos.phobos/std_package.d
Normal file
|
@ -0,0 +1,27 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std;
|
||||
|
||||
import std;
|
||||
|
||||
int len;
|
||||
const r = 6.iota
|
||||
.filter!(a => a % 2) // 1 3 5
|
||||
.map!(a => a * 2) // 2 6 10
|
||||
.tee!(_ => len++)
|
||||
.substitute(6, -6) // 2 -6 10
|
||||
.sum
|
||||
.reverseArgs!format("Sum: %d");
|
||||
|
||||
assert(len == 3);
|
||||
assert(r == "Sum: 6");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std;
|
||||
|
||||
import std;
|
||||
assert(10.iota.map!(a => pow(2, a)).sum == 1023);
|
||||
}
|
||||
|
37
libphobos/testsuite/libphobos.phobos/std_parallelism.d
Normal file
37
libphobos/testsuite/libphobos.phobos/std_parallelism.d
Normal file
|
@ -0,0 +1,37 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.parallelism;
|
||||
|
||||
import std.algorithm.iteration : map;
|
||||
import std.math.operations : isClose;
|
||||
import std.parallelism : taskPool;
|
||||
import std.range : iota;
|
||||
|
||||
// Parallel reduce can be combined with
|
||||
// std.algorithm.iteration.map to interesting effect.
|
||||
// The following example (thanks to Russel Winder)
|
||||
// calculates pi by quadrature using
|
||||
// std.algorithm.map and TaskPool.reduce.
|
||||
// getTerm is evaluated in parallel as needed by
|
||||
// TaskPool.reduce.
|
||||
//
|
||||
// Timings on an Intel i5-3450 quad core machine
|
||||
// for n = 1_000_000_000:
|
||||
//
|
||||
// TaskPool.reduce: 1.067 s
|
||||
// std.algorithm.reduce: 4.011 s
|
||||
|
||||
enum n = 1_000_000;
|
||||
enum delta = 1.0 / n;
|
||||
|
||||
alias getTerm = (int i)
|
||||
{
|
||||
immutable x = ( i - 0.5 ) * delta;
|
||||
return delta / ( 1.0 + x * x ) ;
|
||||
};
|
||||
|
||||
immutable pi = 4.0 * taskPool.reduce!"a + b"(n.iota.map!getTerm);
|
||||
|
||||
assert(pi.isClose(3.14159, 1e-5));
|
||||
}
|
||||
|
611
libphobos/testsuite/libphobos.phobos/std_path.d
Normal file
611
libphobos/testsuite/libphobos.phobos/std_path.d
Normal file
|
@ -0,0 +1,611 @@
|
|||
@safe pure nothrow @nogc unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert( '/'.isDirSeparator);
|
||||
assert( '\\'.isDirSeparator);
|
||||
}
|
||||
else
|
||||
{
|
||||
assert( '/'.isDirSeparator);
|
||||
assert(!'\\'.isDirSeparator);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(baseName!(CaseSensitive.no)("dir/file.EXT", ".ext") == "file");
|
||||
assert(baseName!(CaseSensitive.yes)("dir/file.EXT", ".ext") != "file");
|
||||
|
||||
version (Posix)
|
||||
assert(relativePath!(CaseSensitive.no)("/FOO/bar", "/foo/baz") == "../bar");
|
||||
else
|
||||
assert(relativePath!(CaseSensitive.no)(`c:\FOO\bar`, `c:\foo\baz`) == `..\bar`);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(baseName("dir/file.ext") == "file.ext");
|
||||
assert(baseName("dir/file.ext", ".ext") == "file");
|
||||
assert(baseName("dir/file.ext", ".xyz") == "file.ext");
|
||||
assert(baseName("dir/filename", "name") == "file");
|
||||
assert(baseName("dir/subdir/") == "subdir");
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(baseName(`d:file.ext`) == "file.ext");
|
||||
assert(baseName(`d:\dir\file.ext`) == "file.ext");
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(dirName("") == ".");
|
||||
assert(dirName("file"w) == ".");
|
||||
assert(dirName("dir/"d) == ".");
|
||||
assert(dirName("dir///") == ".");
|
||||
assert(dirName("dir/file"w.dup) == "dir");
|
||||
assert(dirName("dir///file"d.dup) == "dir");
|
||||
assert(dirName("dir/subdir/") == "dir");
|
||||
assert(dirName("/dir/file"w) == "/dir");
|
||||
assert(dirName("/file"d) == "/");
|
||||
assert(dirName("/") == "/");
|
||||
assert(dirName("///") == "/");
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(dirName(`dir\`) == `.`);
|
||||
assert(dirName(`dir\\\`) == `.`);
|
||||
assert(dirName(`dir\file`) == `dir`);
|
||||
assert(dirName(`dir\\\file`) == `dir`);
|
||||
assert(dirName(`dir\subdir\`) == `dir`);
|
||||
assert(dirName(`\dir\file`) == `\dir`);
|
||||
assert(dirName(`\file`) == `\`);
|
||||
assert(dirName(`\`) == `\`);
|
||||
assert(dirName(`\\\`) == `\`);
|
||||
assert(dirName(`d:`) == `d:`);
|
||||
assert(dirName(`d:file`) == `d:`);
|
||||
assert(dirName(`d:\`) == `d:\`);
|
||||
assert(dirName(`d:\file`) == `d:\`);
|
||||
assert(dirName(`d:\dir\file`) == `d:\dir`);
|
||||
assert(dirName(`\\server\share\dir\file`) == `\\server\share\dir`);
|
||||
assert(dirName(`\\server\share\file`) == `\\server\share`);
|
||||
assert(dirName(`\\server\share\`) == `\\server\share`);
|
||||
assert(dirName(`\\server\share`) == `\\server\share`);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(rootName("") is null);
|
||||
assert(rootName("foo") is null);
|
||||
assert(rootName("/") == "/");
|
||||
assert(rootName("/foo/bar") == "/");
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(rootName("d:foo") is null);
|
||||
assert(rootName(`d:\foo`) == `d:\`);
|
||||
assert(rootName(`\\server\share\foo`) == `\\server\share`);
|
||||
assert(rootName(`\\server\share`) == `\\server\share`);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.range : empty;
|
||||
version (Posix) assert(driveName("c:/foo").empty);
|
||||
version (Windows)
|
||||
{
|
||||
assert(driveName(`dir\file`).empty);
|
||||
assert(driveName(`d:file`) == "d:");
|
||||
assert(driveName(`d:\file`) == "d:");
|
||||
assert(driveName("d:") == "d:");
|
||||
assert(driveName(`\\server\share\file`) == `\\server\share`);
|
||||
assert(driveName(`\\server\share\`) == `\\server\share`);
|
||||
assert(driveName(`\\server\share`) == `\\server\share`);
|
||||
|
||||
static assert(driveName(`d:\file`) == "d:");
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(stripDrive(`d:\dir\file`) == `\dir\file`);
|
||||
assert(stripDrive(`\\server\share\dir\file`) == `\dir\file`);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.range : empty;
|
||||
assert(extension("file").empty);
|
||||
assert(extension("file.") == ".");
|
||||
assert(extension("file.ext"w) == ".ext");
|
||||
assert(extension("file.ext1.ext2"d) == ".ext2");
|
||||
assert(extension(".foo".dup).empty);
|
||||
assert(extension(".foo.ext"w.dup) == ".ext");
|
||||
|
||||
static assert(extension("file").empty);
|
||||
static assert(extension("file.ext") == ".ext");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(stripExtension("file") == "file");
|
||||
assert(stripExtension("file.ext") == "file");
|
||||
assert(stripExtension("file.ext1.ext2") == "file.ext1");
|
||||
assert(stripExtension("file.") == "file");
|
||||
assert(stripExtension(".file") == ".file");
|
||||
assert(stripExtension(".file.ext") == ".file");
|
||||
assert(stripExtension("dir/file.ext") == "dir/file");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(setExtension("file", "ext") == "file.ext");
|
||||
assert(setExtension("file"w, ".ext"w) == "file.ext");
|
||||
assert(setExtension("file."d, "ext"d) == "file.ext");
|
||||
assert(setExtension("file.", ".ext") == "file.ext");
|
||||
assert(setExtension("file.old"w, "new"w) == "file.new");
|
||||
assert(setExtension("file.old"d, ".new"d) == "file.new");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.array;
|
||||
assert(withExtension("file", "ext").array == "file.ext");
|
||||
assert(withExtension("file"w, ".ext"w).array == "file.ext");
|
||||
assert(withExtension("file.ext"w, ".").array == "file.");
|
||||
|
||||
import std.utf : byChar, byWchar;
|
||||
assert(withExtension("file".byChar, "ext").array == "file.ext");
|
||||
assert(withExtension("file"w.byWchar, ".ext"w).array == "file.ext"w);
|
||||
assert(withExtension("file.ext"w.byWchar, ".").array == "file."w);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(defaultExtension("file", "ext") == "file.ext");
|
||||
assert(defaultExtension("file", ".ext") == "file.ext");
|
||||
assert(defaultExtension("file.", "ext") == "file.");
|
||||
assert(defaultExtension("file.old", "new") == "file.old");
|
||||
assert(defaultExtension("file.old", ".new") == "file.old");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.array;
|
||||
assert(withDefaultExtension("file", "ext").array == "file.ext");
|
||||
assert(withDefaultExtension("file"w, ".ext").array == "file.ext"w);
|
||||
assert(withDefaultExtension("file.", "ext").array == "file.");
|
||||
assert(withDefaultExtension("file", "").array == "file.");
|
||||
|
||||
import std.utf : byChar, byWchar;
|
||||
assert(withDefaultExtension("file".byChar, "ext").array == "file.ext");
|
||||
assert(withDefaultExtension("file"w.byWchar, ".ext").array == "file.ext"w);
|
||||
assert(withDefaultExtension("file.".byChar, "ext"d).array == "file.");
|
||||
assert(withDefaultExtension("file".byChar, "").array == "file.");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
assert(buildPath("foo", "bar", "baz") == "foo/bar/baz");
|
||||
assert(buildPath("/foo/", "bar/baz") == "/foo/bar/baz");
|
||||
assert(buildPath("/foo", "/bar") == "/bar");
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(buildPath("foo", "bar", "baz") == `foo\bar\baz`);
|
||||
assert(buildPath(`c:\foo`, `bar\baz`) == `c:\foo\bar\baz`);
|
||||
assert(buildPath("foo", `d:\bar`) == `d:\bar`);
|
||||
assert(buildPath("foo", `\bar`) == `\bar`);
|
||||
assert(buildPath(`c:\foo`, `\bar`) == `c:\bar`);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.array;
|
||||
version (Posix)
|
||||
{
|
||||
assert(chainPath("foo", "bar", "baz").array == "foo/bar/baz");
|
||||
assert(chainPath("/foo/", "bar/baz").array == "/foo/bar/baz");
|
||||
assert(chainPath("/foo", "/bar").array == "/bar");
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(chainPath("foo", "bar", "baz").array == `foo\bar\baz`);
|
||||
assert(chainPath(`c:\foo`, `bar\baz`).array == `c:\foo\bar\baz`);
|
||||
assert(chainPath("foo", `d:\bar`).array == `d:\bar`);
|
||||
assert(chainPath("foo", `\bar`).array == `\bar`);
|
||||
assert(chainPath(`c:\foo`, `\bar`).array == `c:\bar`);
|
||||
}
|
||||
|
||||
import std.utf : byChar;
|
||||
version (Posix)
|
||||
{
|
||||
assert(chainPath("foo", "bar", "baz").array == "foo/bar/baz");
|
||||
assert(chainPath("/foo/".byChar, "bar/baz").array == "/foo/bar/baz");
|
||||
assert(chainPath("/foo", "/bar".byChar).array == "/bar");
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(chainPath("foo", "bar", "baz").array == `foo\bar\baz`);
|
||||
assert(chainPath(`c:\foo`.byChar, `bar\baz`).array == `c:\foo\bar\baz`);
|
||||
assert(chainPath("foo", `d:\bar`).array == `d:\bar`);
|
||||
assert(chainPath("foo", `\bar`.byChar).array == `\bar`);
|
||||
assert(chainPath(`c:\foo`, `\bar`w).array == `c:\bar`);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(buildNormalizedPath("foo", "..") == ".");
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
assert(buildNormalizedPath("/foo/./bar/..//baz/") == "/foo/baz");
|
||||
assert(buildNormalizedPath("../foo/.") == "../foo");
|
||||
assert(buildNormalizedPath("/foo", "bar/baz/") == "/foo/bar/baz");
|
||||
assert(buildNormalizedPath("/foo", "/bar/..", "baz") == "/baz");
|
||||
assert(buildNormalizedPath("foo/./bar", "../../", "../baz") == "../baz");
|
||||
assert(buildNormalizedPath("/foo/./bar", "../../baz") == "/baz");
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(buildNormalizedPath(`c:\foo\.\bar/..\\baz\`) == `c:\foo\baz`);
|
||||
assert(buildNormalizedPath(`..\foo\.`) == `..\foo`);
|
||||
assert(buildNormalizedPath(`c:\foo`, `bar\baz\`) == `c:\foo\bar\baz`);
|
||||
assert(buildNormalizedPath(`c:\foo`, `bar/..`) == `c:\foo`);
|
||||
assert(buildNormalizedPath(`\\server\share\foo`, `..\bar`) ==
|
||||
`\\server\share\bar`);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.array;
|
||||
assert(asNormalizedPath("foo/..").array == ".");
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
assert(asNormalizedPath("/foo/./bar/..//baz/").array == "/foo/baz");
|
||||
assert(asNormalizedPath("../foo/.").array == "../foo");
|
||||
assert(asNormalizedPath("/foo/bar/baz/").array == "/foo/bar/baz");
|
||||
assert(asNormalizedPath("/foo/./bar/../../baz").array == "/baz");
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(asNormalizedPath(`c:\foo\.\bar/..\\baz\`).array == `c:\foo\baz`);
|
||||
assert(asNormalizedPath(`..\foo\.`).array == `..\foo`);
|
||||
assert(asNormalizedPath(`c:\foo\bar\baz\`).array == `c:\foo\bar\baz`);
|
||||
assert(asNormalizedPath(`c:\foo\bar/..`).array == `c:\foo`);
|
||||
assert(asNormalizedPath(`\\server\share\foo\..\bar`).array ==
|
||||
`\\server\share\bar`);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.conv : to;
|
||||
|
||||
assert(equal(pathSplitter("/"), ["/"]));
|
||||
assert(equal(pathSplitter("/foo/bar"), ["/", "foo", "bar"]));
|
||||
assert(equal(pathSplitter("foo/../bar//./"), ["foo", "..", "bar", "."]));
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
assert(equal(pathSplitter("//foo/bar"), ["/", "foo", "bar"]));
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(equal(pathSplitter(`foo\..\bar\/.\`), ["foo", "..", "bar", "."]));
|
||||
assert(equal(pathSplitter("c:"), ["c:"]));
|
||||
assert(equal(pathSplitter(`c:\foo\bar`), [`c:\`, "foo", "bar"]));
|
||||
assert(equal(pathSplitter(`c:foo\bar`), ["c:foo", "bar"]));
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
assert( isRooted("/"));
|
||||
assert( isRooted("/foo"));
|
||||
assert(!isRooted("foo"));
|
||||
assert(!isRooted("../foo"));
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert( isRooted(`\`));
|
||||
assert( isRooted(`\foo`));
|
||||
assert( isRooted(`d:\foo`));
|
||||
assert( isRooted(`\\foo\bar`));
|
||||
assert(!isRooted("foo"));
|
||||
assert(!isRooted("d:foo"));
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
assert(absolutePath("some/file", "/foo/bar") == "/foo/bar/some/file");
|
||||
assert(absolutePath("../file", "/foo/bar") == "/foo/bar/../file");
|
||||
assert(absolutePath("/some/file", "/foo/bar") == "/some/file");
|
||||
}
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(absolutePath(`some\file`, `c:\foo\bar`) == `c:\foo\bar\some\file`);
|
||||
assert(absolutePath(`..\file`, `c:\foo\bar`) == `c:\foo\bar\..\file`);
|
||||
assert(absolutePath(`c:\some\file`, `c:\foo\bar`) == `c:\some\file`);
|
||||
assert(absolutePath(`\`, `c:\`) == `c:\`);
|
||||
assert(absolutePath(`\some\file`, `c:\foo\bar`) == `c:\some\file`);
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.array;
|
||||
assert(asAbsolutePath(cast(string) null).array == "");
|
||||
version (Posix)
|
||||
{
|
||||
assert(asAbsolutePath("/foo").array == "/foo");
|
||||
}
|
||||
version (Windows)
|
||||
{
|
||||
assert(asAbsolutePath("c:/foo").array == "c:/foo");
|
||||
}
|
||||
asAbsolutePath("foo");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(relativePath("foo") == "foo");
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
assert(relativePath("foo", "/bar") == "foo");
|
||||
assert(relativePath("/foo/bar", "/foo/bar") == ".");
|
||||
assert(relativePath("/foo/bar", "/foo/baz") == "../bar");
|
||||
assert(relativePath("/foo/bar/baz", "/foo/woo/wee") == "../../bar/baz");
|
||||
assert(relativePath("/foo/bar/baz", "/foo/bar") == "baz");
|
||||
}
|
||||
version (Windows)
|
||||
{
|
||||
assert(relativePath("foo", `c:\bar`) == "foo");
|
||||
assert(relativePath(`c:\foo\bar`, `c:\foo\bar`) == ".");
|
||||
assert(relativePath(`c:\foo\bar`, `c:\foo\baz`) == `..\bar`);
|
||||
assert(relativePath(`c:\foo\bar\baz`, `c:\foo\woo\wee`) == `..\..\bar\baz`);
|
||||
assert(relativePath(`c:\foo\bar\baz`, `c:\foo\bar`) == "baz");
|
||||
assert(relativePath(`c:\foo\bar`, `d:\foo`) == `c:\foo\bar`);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.array;
|
||||
version (Posix)
|
||||
{
|
||||
assert(asRelativePath("foo", "/bar").array == "foo");
|
||||
assert(asRelativePath("/foo/bar", "/foo/bar").array == ".");
|
||||
assert(asRelativePath("/foo/bar", "/foo/baz").array == "../bar");
|
||||
assert(asRelativePath("/foo/bar/baz", "/foo/woo/wee").array == "../../bar/baz");
|
||||
assert(asRelativePath("/foo/bar/baz", "/foo/bar").array == "baz");
|
||||
}
|
||||
else version (Windows)
|
||||
{
|
||||
assert(asRelativePath("foo", `c:\bar`).array == "foo");
|
||||
assert(asRelativePath(`c:\foo\bar`, `c:\foo\bar`).array == ".");
|
||||
assert(asRelativePath(`c:\foo\bar`, `c:\foo\baz`).array == `..\bar`);
|
||||
assert(asRelativePath(`c:\foo\bar\baz`, `c:\foo\woo\wee`).array == `..\..\bar\baz`);
|
||||
assert(asRelativePath(`c:/foo/bar/baz`, `c:\foo\woo\wee`).array == `..\..\bar\baz`);
|
||||
assert(asRelativePath(`c:\foo\bar\baz`, `c:\foo\bar`).array == "baz");
|
||||
assert(asRelativePath(`c:\foo\bar`, `d:\foo`).array == `c:\foo\bar`);
|
||||
assert(asRelativePath(`\\foo\bar`, `c:\foo`).array == `\\foo\bar`);
|
||||
}
|
||||
else
|
||||
static assert(0);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(filenameCharCmp('a', 'a') == 0);
|
||||
assert(filenameCharCmp('a', 'b') < 0);
|
||||
assert(filenameCharCmp('b', 'a') > 0);
|
||||
|
||||
version (linux)
|
||||
{
|
||||
// Same as calling filenameCharCmp!(CaseSensitive.yes)(a, b)
|
||||
assert(filenameCharCmp('A', 'a') < 0);
|
||||
assert(filenameCharCmp('a', 'A') > 0);
|
||||
}
|
||||
version (Windows)
|
||||
{
|
||||
// Same as calling filenameCharCmp!(CaseSensitive.no)(a, b)
|
||||
assert(filenameCharCmp('a', 'A') == 0);
|
||||
assert(filenameCharCmp('a', 'B') < 0);
|
||||
assert(filenameCharCmp('A', 'b') < 0);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(filenameCmp("abc", "abc") == 0);
|
||||
assert(filenameCmp("abc", "abd") < 0);
|
||||
assert(filenameCmp("abc", "abb") > 0);
|
||||
assert(filenameCmp("abc", "abcd") < 0);
|
||||
assert(filenameCmp("abcd", "abc") > 0);
|
||||
|
||||
version (linux)
|
||||
{
|
||||
// Same as calling filenameCmp!(CaseSensitive.yes)(filename1, filename2)
|
||||
assert(filenameCmp("Abc", "abc") < 0);
|
||||
assert(filenameCmp("abc", "Abc") > 0);
|
||||
}
|
||||
version (Windows)
|
||||
{
|
||||
// Same as calling filenameCmp!(CaseSensitive.no)(filename1, filename2)
|
||||
assert(filenameCmp("Abc", "abc") == 0);
|
||||
assert(filenameCmp("abc", "Abc") == 0);
|
||||
assert(filenameCmp("Abc", "abD") < 0);
|
||||
assert(filenameCmp("abc", "AbB") > 0);
|
||||
}
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(globMatch("foo.bar", "*"));
|
||||
assert(globMatch("foo.bar", "*.*"));
|
||||
assert(globMatch(`foo/foo\bar`, "f*b*r"));
|
||||
assert(globMatch("foo.bar", "f???bar"));
|
||||
assert(globMatch("foo.bar", "[fg]???bar"));
|
||||
assert(globMatch("foo.bar", "[!gh]*bar"));
|
||||
assert(globMatch("bar.fooz", "bar.{foo,bif}z"));
|
||||
assert(globMatch("bar.bifz", "bar.{foo,bif}z"));
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
// Same as calling globMatch!(CaseSensitive.no)(path, pattern)
|
||||
assert(globMatch("foo", "Foo"));
|
||||
assert(globMatch("Goo.bar", "[fg]???bar"));
|
||||
}
|
||||
version (linux)
|
||||
{
|
||||
// Same as calling globMatch!(CaseSensitive.yes)(path, pattern)
|
||||
assert(!globMatch("foo", "Foo"));
|
||||
assert(!globMatch("Goo.bar", "[fg]???bar"));
|
||||
}
|
||||
}
|
||||
|
||||
@safe pure @nogc nothrow unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
import std.utf : byCodeUnit;
|
||||
|
||||
assert(isValidFilename("hello.exe".byCodeUnit));
|
||||
}
|
||||
|
||||
@safe pure @nogc nothrow unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
assert(isValidPath("/foo/bar"));
|
||||
assert(!isValidPath("/foo\0/bar"));
|
||||
assert(isValidPath("/"));
|
||||
assert(isValidPath("a"));
|
||||
|
||||
version (Windows)
|
||||
{
|
||||
assert(isValidPath(`c:\`));
|
||||
assert(isValidPath(`c:\foo`));
|
||||
assert(isValidPath(`c:\foo\.\bar\\\..\`));
|
||||
assert(!isValidPath(`!:\foo`));
|
||||
assert(!isValidPath(`c::\foo`));
|
||||
assert(!isValidPath(`c:\foo?`));
|
||||
assert(!isValidPath(`c:\foo.`));
|
||||
|
||||
assert(isValidPath(`\\server\share`));
|
||||
assert(isValidPath(`\\server\share\foo`));
|
||||
assert(isValidPath(`\\server\share\\foo`));
|
||||
assert(!isValidPath(`\\\server\share\foo`));
|
||||
assert(!isValidPath(`\\server\\share\foo`));
|
||||
assert(!isValidPath(`\\ser*er\share\foo`));
|
||||
assert(!isValidPath(`\\server\sha?e\foo`));
|
||||
assert(!isValidPath(`\\server\share\|oo`));
|
||||
|
||||
assert(isValidPath(`\\?\<>:"?*|/\..\.`));
|
||||
assert(!isValidPath("\\\\?\\foo\0bar"));
|
||||
|
||||
assert(!isValidPath(`\\.\PhysicalDisk1`));
|
||||
assert(!isValidPath(`\\`));
|
||||
}
|
||||
|
||||
import std.utf : byCodeUnit;
|
||||
assert(isValidPath("/foo/bar".byCodeUnit));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.path;
|
||||
|
||||
version (Posix)
|
||||
{
|
||||
import std.process : environment;
|
||||
|
||||
auto oldHome = environment["HOME"];
|
||||
scope(exit) environment["HOME"] = oldHome;
|
||||
|
||||
environment["HOME"] = "dmd/test";
|
||||
assert(expandTilde("~/") == "dmd/test/");
|
||||
assert(expandTilde("~") == "dmd/test");
|
||||
}
|
||||
}
|
||||
|
578
libphobos/testsuite/libphobos.phobos/std_random.d
Normal file
578
libphobos/testsuite/libphobos.phobos/std_random.d
Normal file
|
@ -0,0 +1,578 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
import std.algorithm.comparison : among, equal;
|
||||
import std.range : iota;
|
||||
|
||||
// seed a random generator with a constant
|
||||
auto rnd = Random(42);
|
||||
|
||||
// Generate a uniformly-distributed integer in the range [0, 14]
|
||||
// If no random generator is passed, the global `rndGen` would be used
|
||||
auto i = uniform(0, 15, rnd);
|
||||
assert(i >= 0 && i < 15);
|
||||
|
||||
// Generate a uniformly-distributed real in the range [0, 100)
|
||||
auto r = uniform(0.0L, 100.0L, rnd);
|
||||
assert(r >= 0 && r < 100);
|
||||
|
||||
// Sample from a custom type
|
||||
enum Fruit { apple, mango, pear }
|
||||
auto f = rnd.uniform!Fruit;
|
||||
with(Fruit)
|
||||
assert(f.among(apple, mango, pear));
|
||||
|
||||
// Generate a 32-bit random number
|
||||
auto u = uniform!uint(rnd);
|
||||
static assert(is(typeof(u) == uint));
|
||||
|
||||
// Generate a random number in the range in the range [0, 1)
|
||||
auto u2 = uniform01(rnd);
|
||||
assert(u2 >= 0 && u2 < 1);
|
||||
|
||||
// Select an element randomly
|
||||
auto el = 10.iota.choice(rnd);
|
||||
assert(0 <= el && el < 10);
|
||||
|
||||
// Throw a dice with custom proportions
|
||||
// 0: 20%, 1: 10%, 2: 60%
|
||||
auto val = rnd.dice(0.2, 0.1, 0.6);
|
||||
assert(0 <= val && val <= 2);
|
||||
|
||||
auto rnd2 = MinstdRand0(42);
|
||||
|
||||
// Select a random subsample from a range
|
||||
assert(10.iota.randomSample(3, rnd2).equal([7, 8, 9]));
|
||||
|
||||
// Cover all elements in an array in random order
|
||||
version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
|
||||
assert(10.iota.randomCover(rnd2).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5]));
|
||||
else
|
||||
assert(10.iota.randomCover(rnd2).equal([4, 8, 7, 3, 5, 9, 2, 6, 0, 1]));
|
||||
|
||||
// Shuffle an array
|
||||
version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
|
||||
assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([2, 0, 4, 5, 1]));
|
||||
else
|
||||
assert([0, 1, 2, 4, 5].randomShuffle(rnd2).equal([4, 2, 5, 0, 1]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
struct NoRng
|
||||
{
|
||||
@property uint front() {return 0;}
|
||||
@property bool empty() {return false;}
|
||||
void popFront() {}
|
||||
}
|
||||
static assert(!isUniformRNG!(NoRng));
|
||||
|
||||
struct validRng
|
||||
{
|
||||
@property uint front() {return 0;}
|
||||
@property bool empty() {return false;}
|
||||
void popFront() {}
|
||||
|
||||
enum isUniformRandom = true;
|
||||
}
|
||||
static assert(isUniformRNG!(validRng, uint));
|
||||
static assert(isUniformRNG!(validRng));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
struct validRng
|
||||
{
|
||||
@property uint front() {return 0;}
|
||||
@property bool empty() {return false;}
|
||||
void popFront() {}
|
||||
|
||||
enum isUniformRandom = true;
|
||||
}
|
||||
static assert(!isSeedable!(validRng, uint));
|
||||
static assert(!isSeedable!(validRng));
|
||||
|
||||
struct seedRng
|
||||
{
|
||||
@property uint front() {return 0;}
|
||||
@property bool empty() {return false;}
|
||||
void popFront() {}
|
||||
void seed(uint val){}
|
||||
enum isUniformRandom = true;
|
||||
}
|
||||
static assert(isSeedable!(seedRng, uint));
|
||||
static assert(!isSeedable!(seedRng, ulong));
|
||||
static assert(isSeedable!(seedRng));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
alias CPP11LCG = LinearCongruentialEngine!(uint, 48271, 0, 2_147_483_647);
|
||||
|
||||
// seed with a constant
|
||||
auto rnd = CPP11LCG(42);
|
||||
auto n = rnd.front; // same for each run
|
||||
assert(n == 2027382);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
// glibc's LCG
|
||||
alias GLibcLCG = LinearCongruentialEngine!(uint, 1103515245, 12345, 2_147_483_648);
|
||||
|
||||
// Seed with an unpredictable value
|
||||
auto rnd = GLibcLCG(unpredictableSeed);
|
||||
auto n = rnd.front; // different across runs
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
// Visual C++'s LCG
|
||||
alias MSVCLCG = LinearCongruentialEngine!(uint, 214013, 2531011, 0);
|
||||
|
||||
// seed with a constant
|
||||
auto rnd = MSVCLCG(1);
|
||||
auto n = rnd.front; // same for each run
|
||||
assert(n == 2745024);
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
// seed with a constant
|
||||
auto rnd0 = MinstdRand0(1);
|
||||
auto n = rnd0.front;
|
||||
// same for each run
|
||||
assert(n == 16807);
|
||||
|
||||
// Seed with an unpredictable value
|
||||
rnd0.seed(unpredictableSeed);
|
||||
n = rnd0.front; // different across runs
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
// seed with a constant
|
||||
Mt19937 gen;
|
||||
auto n = gen.front; // same for each run
|
||||
assert(n == 3499211612);
|
||||
|
||||
// Seed with an unpredictable value
|
||||
gen.seed(unpredictableSeed);
|
||||
n = gen.front; // different across runs
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
// seed with a constant
|
||||
Mt19937 gen;
|
||||
auto n = gen.front; // same for each run
|
||||
assert(n == 3499211612);
|
||||
|
||||
// Seed with an unpredictable value
|
||||
gen.seed(unpredictableSeed);
|
||||
n = gen.front; // different across runs
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
// Seed with a constant
|
||||
auto gen = Mt19937_64(12345);
|
||||
auto n = gen.front; // same for each run
|
||||
assert(n == 6597103971274460346);
|
||||
|
||||
// Seed with an unpredictable value
|
||||
gen.seed(unpredictableSeed!ulong);
|
||||
n = gen.front; // different across runs
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
alias Xorshift96 = XorshiftEngine!(uint, 96, 10, 5, 26);
|
||||
auto rnd = Xorshift96(42);
|
||||
auto num = rnd.front; // same for each run
|
||||
assert(num == 2704588748);
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
// Seed with a constant
|
||||
auto rnd = Xorshift(1);
|
||||
auto num = rnd.front; // same for each run
|
||||
assert(num == 1405313047);
|
||||
|
||||
// Seed with an unpredictable value
|
||||
rnd.seed(unpredictableSeed);
|
||||
num = rnd.front; // different across rnd
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
auto rnd = Random(unpredictableSeed);
|
||||
auto n = rnd.front;
|
||||
static assert(is(typeof(n) == uint));
|
||||
}
|
||||
|
||||
@safe nothrow @nogc unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
import std.algorithm.iteration : sum;
|
||||
import std.range : take;
|
||||
auto rnd = rndGen;
|
||||
assert(rnd.take(3).sum > 0);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
auto rnd = Random(unpredictableSeed);
|
||||
|
||||
// Generate an integer in [0, 1023]
|
||||
auto a = uniform(0, 1024, rnd);
|
||||
assert(0 <= a && a < 1024);
|
||||
|
||||
// Generate a float in [0, 1)
|
||||
auto b = uniform(0.0f, 1.0f, rnd);
|
||||
assert(0 <= b && b < 1);
|
||||
|
||||
// Generate a float in [0, 1]
|
||||
b = uniform!"[]"(0.0f, 1.0f, rnd);
|
||||
assert(0 <= b && b <= 1);
|
||||
|
||||
// Generate a float in (0, 1)
|
||||
b = uniform!"()"(0.0f, 1.0f, rnd);
|
||||
assert(0 < b && b < 1);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
import std.array : array;
|
||||
import std.range : generate, takeExactly;
|
||||
|
||||
int[] arr = generate!(() => uniform(0, 100)).takeExactly(10).array;
|
||||
assert(arr.length == 10);
|
||||
assert(arr[0] >= 0 && arr[0] < 100);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
import std.conv : to;
|
||||
import std.meta : AliasSeq;
|
||||
import std.range.primitives : isForwardRange;
|
||||
import std.traits : isIntegral, isSomeChar;
|
||||
|
||||
auto gen = Mt19937(123_456_789);
|
||||
static assert(isForwardRange!(typeof(gen)));
|
||||
|
||||
auto a = uniform(0, 1024, gen);
|
||||
assert(0 <= a && a <= 1024);
|
||||
auto b = uniform(0.0f, 1.0f, gen);
|
||||
assert(0 <= b && b < 1, to!string(b));
|
||||
auto c = uniform(0.0, 1.0);
|
||||
assert(0 <= c && c < 1);
|
||||
|
||||
static foreach (T; AliasSeq!(char, wchar, dchar, byte, ubyte, short, ushort,
|
||||
int, uint, long, ulong, float, double, real))
|
||||
{{
|
||||
T lo = 0, hi = 100;
|
||||
|
||||
// Try tests with each of the possible bounds
|
||||
{
|
||||
T init = uniform(lo, hi);
|
||||
size_t i = 50;
|
||||
while (--i && uniform(lo, hi) == init) {}
|
||||
assert(i > 0);
|
||||
}
|
||||
{
|
||||
T init = uniform!"[)"(lo, hi);
|
||||
size_t i = 50;
|
||||
while (--i && uniform(lo, hi) == init) {}
|
||||
assert(i > 0);
|
||||
}
|
||||
{
|
||||
T init = uniform!"(]"(lo, hi);
|
||||
size_t i = 50;
|
||||
while (--i && uniform(lo, hi) == init) {}
|
||||
assert(i > 0);
|
||||
}
|
||||
{
|
||||
T init = uniform!"()"(lo, hi);
|
||||
size_t i = 50;
|
||||
while (--i && uniform(lo, hi) == init) {}
|
||||
assert(i > 0);
|
||||
}
|
||||
{
|
||||
T init = uniform!"[]"(lo, hi);
|
||||
size_t i = 50;
|
||||
while (--i && uniform(lo, hi) == init) {}
|
||||
assert(i > 0);
|
||||
}
|
||||
|
||||
/* Test case with closed boundaries covering whole range
|
||||
* of integral type
|
||||
*/
|
||||
static if (isIntegral!T || isSomeChar!T)
|
||||
{
|
||||
foreach (immutable _; 0 .. 100)
|
||||
{
|
||||
auto u = uniform!"[]"(T.min, T.max);
|
||||
static assert(is(typeof(u) == T));
|
||||
assert(T.min <= u, "Lower bound violation for uniform!\"[]\" with " ~ T.stringof);
|
||||
assert(u <= T.max, "Upper bound violation for uniform!\"[]\" with " ~ T.stringof);
|
||||
}
|
||||
}
|
||||
}}
|
||||
|
||||
auto reproRng = Xorshift(239842);
|
||||
|
||||
static foreach (T; AliasSeq!(char, wchar, dchar, byte, ubyte, short,
|
||||
ushort, int, uint, long, ulong))
|
||||
{{
|
||||
T lo = T.min + 10, hi = T.max - 10;
|
||||
T init = uniform(lo, hi, reproRng);
|
||||
size_t i = 50;
|
||||
while (--i && uniform(lo, hi, reproRng) == init) {}
|
||||
assert(i > 0);
|
||||
}}
|
||||
|
||||
{
|
||||
bool sawLB = false, sawUB = false;
|
||||
foreach (i; 0 .. 50)
|
||||
{
|
||||
auto x = uniform!"[]"('a', 'd', reproRng);
|
||||
if (x == 'a') sawLB = true;
|
||||
if (x == 'd') sawUB = true;
|
||||
assert('a' <= x && x <= 'd');
|
||||
}
|
||||
assert(sawLB && sawUB);
|
||||
}
|
||||
|
||||
{
|
||||
bool sawLB = false, sawUB = false;
|
||||
foreach (i; 0 .. 50)
|
||||
{
|
||||
auto x = uniform('a', 'd', reproRng);
|
||||
if (x == 'a') sawLB = true;
|
||||
if (x == 'c') sawUB = true;
|
||||
assert('a' <= x && x < 'd');
|
||||
}
|
||||
assert(sawLB && sawUB);
|
||||
}
|
||||
|
||||
{
|
||||
bool sawLB = false, sawUB = false;
|
||||
foreach (i; 0 .. 50)
|
||||
{
|
||||
immutable int lo = -2, hi = 2;
|
||||
auto x = uniform!"()"(lo, hi, reproRng);
|
||||
if (x == (lo+1)) sawLB = true;
|
||||
if (x == (hi-1)) sawUB = true;
|
||||
assert(lo < x && x < hi);
|
||||
}
|
||||
assert(sawLB && sawUB);
|
||||
}
|
||||
|
||||
{
|
||||
bool sawLB = false, sawUB = false;
|
||||
foreach (i; 0 .. 50)
|
||||
{
|
||||
immutable ubyte lo = 0, hi = 5;
|
||||
auto x = uniform(lo, hi, reproRng);
|
||||
if (x == lo) sawLB = true;
|
||||
if (x == (hi-1)) sawUB = true;
|
||||
assert(lo <= x && x < hi);
|
||||
}
|
||||
assert(sawLB && sawUB);
|
||||
}
|
||||
|
||||
{
|
||||
foreach (i; 0 .. 30)
|
||||
{
|
||||
assert(i == uniform(i, i+1, reproRng));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
auto rnd = MinstdRand0(42);
|
||||
|
||||
assert(rnd.uniform!ubyte == 102);
|
||||
assert(rnd.uniform!ulong == 4838462006927449017);
|
||||
|
||||
enum Fruit { apple, mango, pear }
|
||||
version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
|
||||
assert(rnd.uniform!Fruit == Fruit.mango);
|
||||
}
|
||||
|
||||
@safe @nogc unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
import std.math.operations : feqrel;
|
||||
|
||||
auto rnd = MinstdRand0(42);
|
||||
|
||||
// Generate random numbers in the range in the range [0, 1)
|
||||
auto u1 = uniform01(rnd);
|
||||
assert(u1 >= 0 && u1 < 1);
|
||||
|
||||
auto u2 = rnd.uniform01!float;
|
||||
assert(u2 >= 0 && u2 < 1);
|
||||
|
||||
// Confirm that the random values with the initial seed 42 are 0.000328707 and 0.524587
|
||||
assert(u1.feqrel(0.000328707) > 20);
|
||||
assert(u2.feqrel(0.524587) > 20);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
import std.algorithm.iteration : reduce;
|
||||
import std.math.operations : isClose;
|
||||
|
||||
auto a = uniformDistribution(5);
|
||||
assert(a.length == 5);
|
||||
assert(isClose(reduce!"a + b"(a), 1));
|
||||
|
||||
a = uniformDistribution(10, a);
|
||||
assert(a.length == 10);
|
||||
assert(isClose(reduce!"a + b"(a), 1));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
auto rnd = MinstdRand0(42);
|
||||
|
||||
auto elem = [1, 2, 3, 4, 5].choice(rnd);
|
||||
version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
|
||||
assert(elem == 3);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
auto rnd = MinstdRand0(42);
|
||||
|
||||
auto arr = [1, 2, 3, 4, 5].randomShuffle(rnd);
|
||||
version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
|
||||
assert(arr == [3, 5, 2, 4, 1]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
auto rnd = MinstdRand0(42);
|
||||
|
||||
auto arr = [1, 2, 3, 4, 5, 6];
|
||||
arr = arr.dup.partialShuffle(1, rnd);
|
||||
|
||||
version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
|
||||
assert(arr == [2, 1, 3, 4, 5, 6]); // 1<->2
|
||||
|
||||
arr = arr.dup.partialShuffle(2, rnd);
|
||||
version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
|
||||
assert(arr == [1, 4, 3, 2, 5, 6]); // 1<->2, 2<->4
|
||||
|
||||
arr = arr.dup.partialShuffle(3, rnd);
|
||||
version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
|
||||
assert(arr == [5, 4, 6, 2, 1, 3]); // 1<->5, 2<->4, 3<->6
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
auto d6 = 1 + dice(1, 1, 1, 1, 1, 1); // fair dice roll
|
||||
auto d6b = 1 + dice(2, 1, 1, 1, 1, 1); // double the chance to roll '1'
|
||||
|
||||
auto x = dice(0.5, 0.5); // x is 0 or 1 in equal proportions
|
||||
auto y = dice(50, 50); // y is 0 or 1 in equal proportions
|
||||
auto z = dice(70, 20, 10); // z is 0 70% of the time, 1 20% of the time,
|
||||
// and 2 10% of the time
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
auto rnd = MinstdRand0(42);
|
||||
auto z = rnd.dice(70, 20, 10);
|
||||
assert(z == 0);
|
||||
z = rnd.dice(30, 20, 40, 10);
|
||||
assert(z == 2);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
auto rnd = Xorshift(123_456_789);
|
||||
auto i = dice(rnd, 0.0, 100.0);
|
||||
assert(i == 1);
|
||||
i = dice(rnd, 100.0, 0.0);
|
||||
assert(i == 0);
|
||||
|
||||
i = dice(100U, 0U);
|
||||
assert(i == 0);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : iota;
|
||||
auto rnd = MinstdRand0(42);
|
||||
|
||||
version (D_LP64) // https://issues.dlang.org/show_bug.cgi?id=15147
|
||||
assert(10.iota.randomCover(rnd).equal([7, 4, 2, 0, 1, 6, 8, 3, 9, 5]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.random;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : iota;
|
||||
auto rnd = MinstdRand0(42);
|
||||
assert(10.iota.randomSample(3, rnd).equal([7, 8, 9]));
|
||||
}
|
||||
|
32
libphobos/testsuite/libphobos.phobos/std_range_interfaces.d
Normal file
32
libphobos/testsuite/libphobos.phobos/std_range_interfaces.d
Normal file
|
@ -0,0 +1,32 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.range.interfaces;
|
||||
|
||||
import std.algorithm.iteration : map;
|
||||
import std.range : iota;
|
||||
|
||||
void useRange(InputRange!int range) {
|
||||
// Function body.
|
||||
}
|
||||
|
||||
// Create a range type.
|
||||
auto squares = map!"a * a"(iota(10));
|
||||
|
||||
// Wrap it in an interface.
|
||||
auto squaresWrapped = inputRangeObject(squares);
|
||||
|
||||
// Use it.
|
||||
useRange(squaresWrapped);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.interfaces;
|
||||
|
||||
import std.array;
|
||||
auto app = appender!(uint[])();
|
||||
auto appWrapped = outputRangeObject!(uint, uint[])(app);
|
||||
static assert(is(typeof(appWrapped) : OutputRange!(uint[])));
|
||||
static assert(is(typeof(appWrapped) : OutputRange!(uint)));
|
||||
}
|
||||
|
1346
libphobos/testsuite/libphobos.phobos/std_range_package.d
Normal file
1346
libphobos/testsuite/libphobos.phobos/std_range_package.d
Normal file
File diff suppressed because it is too large
Load diff
591
libphobos/testsuite/libphobos.phobos/std_range_primitives.d
Normal file
591
libphobos/testsuite/libphobos.phobos/std_range_primitives.d
Normal file
|
@ -0,0 +1,591 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
struct A {}
|
||||
struct B
|
||||
{
|
||||
void popFront();
|
||||
@property bool empty();
|
||||
@property int front();
|
||||
}
|
||||
static assert(!isInputRange!A);
|
||||
static assert( isInputRange!B);
|
||||
static assert( isInputRange!(int[]));
|
||||
static assert( isInputRange!(char[]));
|
||||
static assert(!isInputRange!(char[4]));
|
||||
static assert( isInputRange!(inout(int)[]));
|
||||
static assert(!isInputRange!(int[], string));
|
||||
static assert( isInputRange!(int[], int));
|
||||
static assert( isInputRange!(int[], const int));
|
||||
static assert(!isInputRange!(int[], immutable int));
|
||||
|
||||
static assert(!isInputRange!(const(int)[], int));
|
||||
static assert( isInputRange!(const(int)[], const int));
|
||||
static assert(!isInputRange!(const(int)[], immutable int));
|
||||
|
||||
static assert(!isInputRange!(immutable(int)[], int));
|
||||
static assert( isInputRange!(immutable(int)[], const int));
|
||||
static assert( isInputRange!(immutable(int)[], immutable int));
|
||||
|
||||
static struct NotDefaultConstructible
|
||||
{
|
||||
@disable this();
|
||||
void popFront();
|
||||
@property bool empty();
|
||||
@property int front();
|
||||
}
|
||||
static assert( isInputRange!NotDefaultConstructible);
|
||||
|
||||
static struct NotDefaultConstructibleOrCopyable
|
||||
{
|
||||
@disable this();
|
||||
@disable this(this);
|
||||
void popFront();
|
||||
@property bool empty();
|
||||
@property int front();
|
||||
}
|
||||
static assert(isInputRange!NotDefaultConstructibleOrCopyable);
|
||||
|
||||
static struct Frontless
|
||||
{
|
||||
void popFront();
|
||||
@property bool empty();
|
||||
}
|
||||
static assert(!isInputRange!Frontless);
|
||||
|
||||
static struct VoidFront
|
||||
{
|
||||
void popFront();
|
||||
@property bool empty();
|
||||
void front();
|
||||
}
|
||||
static assert(!isInputRange!VoidFront);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.traits : isSomeChar;
|
||||
|
||||
static struct A
|
||||
{
|
||||
string data;
|
||||
|
||||
void put(C)(C c)
|
||||
if (isSomeChar!C)
|
||||
{
|
||||
data ~= c;
|
||||
}
|
||||
}
|
||||
static assert(isOutputRange!(A, char));
|
||||
|
||||
auto a = A();
|
||||
put(a, "Hello");
|
||||
assert(a.data == "Hello");
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
int[] a = [1, 2, 3], b = [10, 20];
|
||||
auto c = a;
|
||||
put(a, b);
|
||||
assert(c == [10, 20, 3]);
|
||||
// at this point, a was advanced twice, so it only contains
|
||||
// its last element while c represents the whole array
|
||||
assert(a == [3]);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
// the elements must be mutable, so using string or const(char)[]
|
||||
// won't compile
|
||||
char[] s1 = new char[13];
|
||||
auto r1 = s1;
|
||||
put(r1, "Hello, World!"w);
|
||||
assert(s1 == "Hello, World!");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
void myprint(scope const(char)[] s) { }
|
||||
static assert(isOutputRange!(typeof(&myprint), char));
|
||||
|
||||
static assert( isOutputRange!(char[], char));
|
||||
static assert( isOutputRange!(dchar[], wchar));
|
||||
static assert( isOutputRange!(dchar[], dchar));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
static assert(!isForwardRange!(int));
|
||||
static assert( isForwardRange!(int[]));
|
||||
static assert( isForwardRange!(inout(int)[]));
|
||||
|
||||
static assert( isForwardRange!(int[], const int));
|
||||
static assert(!isForwardRange!(int[], immutable int));
|
||||
|
||||
static assert(!isForwardRange!(const(int)[], int));
|
||||
static assert( isForwardRange!(const(int)[], const int));
|
||||
static assert(!isForwardRange!(const(int)[], immutable int));
|
||||
|
||||
static assert(!isForwardRange!(immutable(int)[], int));
|
||||
static assert( isForwardRange!(immutable(int)[], const int));
|
||||
static assert( isForwardRange!(immutable(int)[], immutable int));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
alias R = int[];
|
||||
R r = [0,1];
|
||||
static assert(isForwardRange!R); // is forward range
|
||||
r.popBack(); // can invoke popBack
|
||||
auto t = r.back; // can get the back of the range
|
||||
auto w = r.front;
|
||||
static assert(is(typeof(t) == typeof(w))); // same type for front and back
|
||||
|
||||
// Checking the element type
|
||||
static assert( isBidirectionalRange!(int[], const int));
|
||||
static assert(!isBidirectionalRange!(int[], immutable int));
|
||||
|
||||
static assert(!isBidirectionalRange!(const(int)[], int));
|
||||
static assert( isBidirectionalRange!(const(int)[], const int));
|
||||
static assert(!isBidirectionalRange!(const(int)[], immutable int));
|
||||
|
||||
static assert(!isBidirectionalRange!(immutable(int)[], int));
|
||||
static assert( isBidirectionalRange!(immutable(int)[], const int));
|
||||
static assert( isBidirectionalRange!(immutable(int)[], immutable int));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.traits : isAggregateType, isAutodecodableString;
|
||||
|
||||
alias R = int[];
|
||||
|
||||
// range is finite and bidirectional or infinite and forward.
|
||||
static assert(isBidirectionalRange!R ||
|
||||
isForwardRange!R && isInfinite!R);
|
||||
|
||||
R r = [0,1];
|
||||
auto e = r[1]; // can index
|
||||
auto f = r.front;
|
||||
static assert(is(typeof(e) == typeof(f))); // same type for indexed and front
|
||||
static assert(!(isAutodecodableString!R && !isAggregateType!R)); // narrow strings cannot be indexed as ranges
|
||||
static assert(hasLength!R || isInfinite!R); // must have length or be infinite
|
||||
|
||||
// $ must work as it does with arrays if opIndex works with $
|
||||
static if (is(typeof(r[$])))
|
||||
{
|
||||
static assert(is(typeof(f) == typeof(r[$])));
|
||||
|
||||
// $ - 1 doesn't make sense with infinite ranges but needs to work
|
||||
// with finite ones.
|
||||
static if (!isInfinite!R)
|
||||
static assert(is(typeof(f) == typeof(r[$ - 1])));
|
||||
}
|
||||
|
||||
// Checking the element type
|
||||
static assert( isRandomAccessRange!(int[], const int));
|
||||
static assert(!isRandomAccessRange!(int[], immutable int));
|
||||
|
||||
static assert(!isRandomAccessRange!(const(int)[], int));
|
||||
static assert( isRandomAccessRange!(const(int)[], const int));
|
||||
static assert(!isRandomAccessRange!(const(int)[], immutable int));
|
||||
|
||||
static assert(!isRandomAccessRange!(immutable(int)[], int));
|
||||
static assert( isRandomAccessRange!(immutable(int)[], const int));
|
||||
static assert( isRandomAccessRange!(immutable(int)[], immutable int));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.algorithm.iteration : map;
|
||||
import std.range : iota, repeat;
|
||||
|
||||
static struct HasPostblit
|
||||
{
|
||||
this(this) {}
|
||||
}
|
||||
|
||||
auto nonMobile = map!"a"(repeat(HasPostblit.init));
|
||||
static assert(!hasMobileElements!(typeof(nonMobile)));
|
||||
static assert( hasMobileElements!(int[]));
|
||||
static assert( hasMobileElements!(inout(int)[]));
|
||||
static assert( hasMobileElements!(typeof(iota(1000))));
|
||||
|
||||
static assert( hasMobileElements!( string));
|
||||
static assert( hasMobileElements!(dstring));
|
||||
static assert( hasMobileElements!( char[]));
|
||||
static assert( hasMobileElements!(dchar[]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.range : iota;
|
||||
|
||||
// Standard arrays: returns the type of the elements of the array
|
||||
static assert(is(ElementType!(int[]) == int));
|
||||
|
||||
// Accessing .front retrieves the decoded dchar
|
||||
static assert(is(ElementType!(char[]) == dchar)); // rvalue
|
||||
static assert(is(ElementType!(dchar[]) == dchar)); // lvalue
|
||||
|
||||
// Ditto
|
||||
static assert(is(ElementType!(string) == dchar));
|
||||
static assert(is(ElementType!(dstring) == immutable(dchar)));
|
||||
|
||||
// For ranges it gets the type of .front.
|
||||
auto range = iota(0, 10);
|
||||
static assert(is(ElementType!(typeof(range)) == int));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.range : iota;
|
||||
// internally the range stores the encoded type
|
||||
static assert(is(ElementEncodingType!(char[]) == char));
|
||||
|
||||
static assert(is(ElementEncodingType!(wstring) == immutable(wchar)));
|
||||
|
||||
static assert(is(ElementEncodingType!(byte[]) == byte));
|
||||
|
||||
auto range = iota(0, 10);
|
||||
static assert(is(ElementEncodingType!(typeof(range)) == int));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
static assert(!hasSwappableElements!(const int[]));
|
||||
static assert(!hasSwappableElements!(const(int)[]));
|
||||
static assert(!hasSwappableElements!(inout(int)[]));
|
||||
static assert( hasSwappableElements!(int[]));
|
||||
|
||||
static assert(!hasSwappableElements!( string));
|
||||
static assert(!hasSwappableElements!(dstring));
|
||||
static assert(!hasSwappableElements!( char[]));
|
||||
static assert( hasSwappableElements!(dchar[]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
static assert(!hasAssignableElements!(const int[]));
|
||||
static assert(!hasAssignableElements!(const(int)[]));
|
||||
static assert( hasAssignableElements!(int[]));
|
||||
static assert(!hasAssignableElements!(inout(int)[]));
|
||||
|
||||
static assert(!hasAssignableElements!( string));
|
||||
static assert(!hasAssignableElements!(dstring));
|
||||
static assert(!hasAssignableElements!( char[]));
|
||||
static assert( hasAssignableElements!(dchar[]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.range : iota, chain;
|
||||
|
||||
static assert( hasLvalueElements!(int[]));
|
||||
static assert( hasLvalueElements!(const(int)[]));
|
||||
static assert( hasLvalueElements!(inout(int)[]));
|
||||
static assert( hasLvalueElements!(immutable(int)[]));
|
||||
static assert(!hasLvalueElements!(typeof(iota(3))));
|
||||
|
||||
static assert(!hasLvalueElements!( string));
|
||||
static assert( hasLvalueElements!(dstring));
|
||||
static assert(!hasLvalueElements!( char[]));
|
||||
static assert( hasLvalueElements!(dchar[]));
|
||||
|
||||
auto c = chain([1, 2, 3], [4, 5, 6]);
|
||||
static assert( hasLvalueElements!(typeof(c)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
static assert(!hasLength!(char[]));
|
||||
static assert( hasLength!(int[]));
|
||||
static assert( hasLength!(inout(int)[]));
|
||||
|
||||
struct A { size_t length() { return 0; } }
|
||||
struct B { @property size_t length() { return 0; } }
|
||||
static assert( hasLength!(A));
|
||||
static assert( hasLength!(B));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.range : Repeat;
|
||||
static assert(!isInfinite!(int[]));
|
||||
static assert( isInfinite!(Repeat!(int)));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.range : takeExactly;
|
||||
static assert( hasSlicing!(int[]));
|
||||
static assert( hasSlicing!(const(int)[]));
|
||||
static assert(!hasSlicing!(const int[]));
|
||||
static assert( hasSlicing!(inout(int)[]));
|
||||
static assert(!hasSlicing!(inout int []));
|
||||
static assert( hasSlicing!(immutable(int)[]));
|
||||
static assert(!hasSlicing!(immutable int[]));
|
||||
static assert(!hasSlicing!string);
|
||||
static assert( hasSlicing!dstring);
|
||||
|
||||
enum rangeFuncs = "@property int front();" ~
|
||||
"void popFront();" ~
|
||||
"@property bool empty();" ~
|
||||
"@property auto save() { return this; }" ~
|
||||
"@property size_t length();";
|
||||
|
||||
struct A { mixin(rangeFuncs); int opSlice(size_t, size_t); }
|
||||
struct B { mixin(rangeFuncs); B opSlice(size_t, size_t); }
|
||||
struct C { mixin(rangeFuncs); @disable this(); C opSlice(size_t, size_t); }
|
||||
struct D { mixin(rangeFuncs); int[] opSlice(size_t, size_t); }
|
||||
static assert(!hasSlicing!(A));
|
||||
static assert( hasSlicing!(B));
|
||||
static assert( hasSlicing!(C));
|
||||
static assert(!hasSlicing!(D));
|
||||
|
||||
struct InfOnes
|
||||
{
|
||||
enum empty = false;
|
||||
void popFront() {}
|
||||
@property int front() { return 1; }
|
||||
@property InfOnes save() { return this; }
|
||||
auto opSlice(size_t i, size_t j) { return takeExactly(this, j - i); }
|
||||
auto opSlice(size_t i, Dollar d) { return this; }
|
||||
|
||||
struct Dollar {}
|
||||
Dollar opDollar() const { return Dollar.init; }
|
||||
}
|
||||
|
||||
static assert(hasSlicing!InfOnes);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.range : iota;
|
||||
|
||||
assert(10.iota.walkLength == 10);
|
||||
// iota has a length function, and therefore the
|
||||
// doesn't have to be walked, and the upTo
|
||||
// parameter is ignored
|
||||
assert(10.iota.walkLength(5) == 10);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
int[] a = [ 1, 2, 3, 4, 5 ];
|
||||
a.popFrontN(2);
|
||||
assert(a == [ 3, 4, 5 ]);
|
||||
a.popFrontN(7);
|
||||
assert(a == [ ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : iota;
|
||||
auto LL = iota(1L, 7L);
|
||||
auto r = popFrontN(LL, 2);
|
||||
assert(equal(LL, [3L, 4L, 5L, 6L]));
|
||||
assert(r == 2);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
int[] a = [ 1, 2, 3, 4, 5 ];
|
||||
a.popBackN(2);
|
||||
assert(a == [ 1, 2, 3 ]);
|
||||
a.popBackN(7);
|
||||
assert(a == [ ]);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.range : iota;
|
||||
auto LL = iota(1L, 7L);
|
||||
auto r = popBackN(LL, 2);
|
||||
assert(equal(LL, [1L, 2L, 3L, 4L]));
|
||||
assert(r == 2);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.algorithm.iteration : filterBidirectional;
|
||||
|
||||
auto a = [1, 2, 3];
|
||||
a.popFrontExactly(1);
|
||||
assert(a == [2, 3]);
|
||||
a.popBackExactly(1);
|
||||
assert(a == [2]);
|
||||
|
||||
string s = "日本語";
|
||||
s.popFrontExactly(1);
|
||||
assert(s == "本語");
|
||||
s.popBackExactly(1);
|
||||
assert(s == "本");
|
||||
|
||||
auto bd = filterBidirectional!"true"([1, 2, 3]);
|
||||
bd.popFrontExactly(1);
|
||||
assert(bd.equal([2, 3]));
|
||||
bd.popBackExactly(1);
|
||||
assert(bd.equal([2]));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
auto a = [ 1, 2, 3 ];
|
||||
assert(moveFront(a) == 1);
|
||||
assert(a.length == 3);
|
||||
|
||||
// define a perfunctory input range
|
||||
struct InputRange
|
||||
{
|
||||
enum bool empty = false;
|
||||
enum int front = 7;
|
||||
void popFront() {}
|
||||
int moveFront() { return 43; }
|
||||
}
|
||||
InputRange r;
|
||||
// calls r.moveFront
|
||||
assert(moveFront(r) == 43);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
struct TestRange
|
||||
{
|
||||
int payload = 5;
|
||||
@property bool empty() { return false; }
|
||||
@property TestRange save() { return this; }
|
||||
@property ref int front() return { return payload; }
|
||||
@property ref int back() return { return payload; }
|
||||
void popFront() { }
|
||||
void popBack() { }
|
||||
}
|
||||
static assert(isBidirectionalRange!TestRange);
|
||||
TestRange r;
|
||||
auto x = moveBack(r);
|
||||
assert(x == 5);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
auto a = [1,2,3,4];
|
||||
foreach (idx, it; a)
|
||||
{
|
||||
assert(it == moveAt(a, idx));
|
||||
}
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
auto a = [ 1, 2, 3 ];
|
||||
assert(!a.empty);
|
||||
assert(a[3 .. $].empty);
|
||||
|
||||
int[string] b;
|
||||
assert(b.empty);
|
||||
b["zero"] = 0;
|
||||
assert(!b.empty);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
auto a = [ 1, 2, 3 ];
|
||||
auto b = a.save;
|
||||
assert(b is a);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
auto a = [ 1, 2, 3 ];
|
||||
a.popFront();
|
||||
assert(a == [ 2, 3 ]);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
auto a = [ 1, 2, 3 ];
|
||||
a.popBack();
|
||||
assert(a == [ 1, 2 ]);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
int[] a = [ 1, 2, 3 ];
|
||||
assert(a.front == 1);
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.range.primitives;
|
||||
|
||||
int[] a = [ 1, 2, 3 ];
|
||||
assert(a.back == 3);
|
||||
a.back += 4;
|
||||
assert(a.back == 7);
|
||||
}
|
||||
|
175
libphobos/testsuite/libphobos.phobos/std_regex_package.d
Normal file
175
libphobos/testsuite/libphobos.phobos/std_regex_package.d
Normal file
|
@ -0,0 +1,175 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
void test(S)()
|
||||
{
|
||||
// multi-pattern regex example
|
||||
S[] arr = [`([a-z]+):(\d+)`, `(\d+),\d+`];
|
||||
auto multi = regex(arr); // multi regex
|
||||
S str = "abc:43 12,34";
|
||||
auto m = str.matchAll(multi);
|
||||
assert(m.front.whichPattern == 1);
|
||||
assert(m.front[1] == "abc");
|
||||
assert(m.front[2] == "43");
|
||||
m.popFront();
|
||||
assert(m.front.whichPattern == 2);
|
||||
assert(m.front[1] == "12");
|
||||
}
|
||||
|
||||
import std.meta : AliasSeq;
|
||||
static foreach (C; AliasSeq!(string, wstring, dstring))
|
||||
// Test with const array of patterns - see https://issues.dlang.org/show_bug.cgi?id=20301
|
||||
static foreach (S; AliasSeq!(C, const C, immutable C))
|
||||
test!S();
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
import std.regex;
|
||||
assert(matchFirst("abc", "[0-9]+", "[a-z]+").whichPattern == 2);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
import std.range.primitives : popFrontN;
|
||||
|
||||
auto c = matchFirst("@abc#", regex(`(\w)(\w)(\w)`));
|
||||
assert(c.pre == "@"); // Part of input preceding match
|
||||
assert(c.post == "#"); // Immediately after match
|
||||
assert(c.hit == c[0] && c.hit == "abc"); // The whole match
|
||||
assert(c[2] == "b");
|
||||
assert(c.front == "abc");
|
||||
c.popFront();
|
||||
assert(c.front == "a");
|
||||
assert(c.back == "c");
|
||||
c.popBack();
|
||||
assert(c.back == "b");
|
||||
popFrontN(c, 2);
|
||||
assert(c.empty);
|
||||
|
||||
assert(!matchFirst("nothing", "something"));
|
||||
|
||||
// Captures that are not matched will be null.
|
||||
c = matchFirst("ac", regex(`a(b)?c`));
|
||||
assert(c);
|
||||
assert(!c[1]);
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
assert(replaceFirst("noon", regex("n"), "[$&]") == "[n]oon");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
import std.conv : to;
|
||||
string list = "#21 out of 46";
|
||||
string newList = replaceFirst!(cap => to!string(to!int(cap.hit)+1))
|
||||
(list, regex(`[0-9]+`));
|
||||
assert(newList == "#22 out of 46");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
import std.array;
|
||||
string m1 = "first message\n";
|
||||
string m2 = "second message\n";
|
||||
auto result = appender!string();
|
||||
replaceFirstInto(result, m1, regex(`([a-z]+) message`), "$1");
|
||||
//equivalent of the above with user-defined callback
|
||||
replaceFirstInto!(cap=>cap[1])(result, m2, regex(`([a-z]+) message`));
|
||||
assert(result.data == "first\nsecond\n");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
// insert comma as thousands delimiter
|
||||
auto re = regex(r"(?<=\d)(?=(\d\d\d)+\b)","g");
|
||||
assert(replaceAll("12000 + 42100 = 54100", re, ",") == "12,000 + 42,100 = 54,100");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
string baz(Captures!(string) m)
|
||||
{
|
||||
import std.string : toUpper;
|
||||
return toUpper(m.hit);
|
||||
}
|
||||
// Capitalize the letters 'a' and 'r':
|
||||
auto s = replaceAll!(baz)("Strap a rocket engine on a chicken.",
|
||||
regex("[ar]"));
|
||||
assert(s == "StRAp A Rocket engine on A chicken.");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
// insert comma as thousands delimiter in fifty randomly produced big numbers
|
||||
import std.array, std.conv, std.random, std.range;
|
||||
static re = regex(`(?<=\d)(?=(\d\d\d)+\b)`, "g");
|
||||
auto sink = appender!(char [])();
|
||||
enum ulong min = 10UL ^^ 10, max = 10UL ^^ 19;
|
||||
foreach (i; 0 .. 50)
|
||||
{
|
||||
sink.clear();
|
||||
replaceAllInto(sink, text(uniform(min, max)), re, ",");
|
||||
foreach (pos; iota(sink.data.length - 4, 0, -4))
|
||||
assert(sink.data[pos] == ',');
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
auto s1 = ", abc, de, fg, hi, ";
|
||||
assert(equal(splitter(s1, regex(", *")),
|
||||
["", "abc", "de", "fg", "hi", ""]));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.typecons : Yes;
|
||||
|
||||
auto pattern = regex(`([\.,])`);
|
||||
|
||||
assert("2003.04.05"
|
||||
.splitter!(Yes.keepSeparators)(pattern)
|
||||
.equal(["2003", ".", "04", ".", "05"]));
|
||||
|
||||
assert(",1,2,3"
|
||||
.splitter!(Yes.keepSeparators)(pattern)
|
||||
.equal([",", "1", ",", "2", ",", "3"]));
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.regex;
|
||||
|
||||
import std.algorithm.comparison;
|
||||
import std.regex;
|
||||
string s = `This is {unfriendly} to *regex*`;
|
||||
assert(s.escaper.equal(`This is \{unfriendly\} to \*regex\*`));
|
||||
}
|
||||
|
85
libphobos/testsuite/libphobos.phobos/std_signals.d
Normal file
85
libphobos/testsuite/libphobos.phobos/std_signals.d
Normal file
|
@ -0,0 +1,85 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.signals;
|
||||
|
||||
import std.signals;
|
||||
|
||||
int observedMessageCounter = 0;
|
||||
|
||||
class Observer
|
||||
{ // our slot
|
||||
void watch(string msg, int value)
|
||||
{
|
||||
switch (observedMessageCounter++)
|
||||
{
|
||||
case 0:
|
||||
assert(msg == "setting new value");
|
||||
assert(value == 4);
|
||||
break;
|
||||
case 1:
|
||||
assert(msg == "setting new value");
|
||||
assert(value == 6);
|
||||
break;
|
||||
default:
|
||||
assert(0, "Unknown observation");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class Observer2
|
||||
{ // our slot
|
||||
void watch(string msg, int value)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
class Foo
|
||||
{
|
||||
int value() { return _value; }
|
||||
|
||||
int value(int v)
|
||||
{
|
||||
if (v != _value)
|
||||
{ _value = v;
|
||||
// call all the connected slots with the two parameters
|
||||
emit("setting new value", v);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// Mix in all the code we need to make Foo into a signal
|
||||
mixin Signal!(string, int);
|
||||
|
||||
private :
|
||||
int _value;
|
||||
}
|
||||
|
||||
Foo a = new Foo;
|
||||
Observer o = new Observer;
|
||||
auto o2 = new Observer2;
|
||||
auto o3 = new Observer2;
|
||||
auto o4 = new Observer2;
|
||||
auto o5 = new Observer2;
|
||||
|
||||
a.value = 3; // should not call o.watch()
|
||||
a.connect(&o.watch); // o.watch is the slot
|
||||
a.connect(&o2.watch);
|
||||
a.connect(&o3.watch);
|
||||
a.connect(&o4.watch);
|
||||
a.connect(&o5.watch);
|
||||
a.value = 4; // should call o.watch()
|
||||
a.disconnect(&o.watch); // o.watch is no longer a slot
|
||||
a.disconnect(&o3.watch);
|
||||
a.disconnect(&o5.watch);
|
||||
a.disconnect(&o4.watch);
|
||||
a.disconnect(&o2.watch);
|
||||
a.value = 5; // so should not call o.watch()
|
||||
a.connect(&o2.watch);
|
||||
a.connect(&o.watch); // connect again
|
||||
a.value = 6; // should call o.watch()
|
||||
destroy(o); // destroying o should automatically disconnect it
|
||||
a.value = 7; // should not call o.watch()
|
||||
|
||||
assert(observedMessageCounter == 2);
|
||||
}
|
||||
|
66
libphobos/testsuite/libphobos.phobos/std_socket.d
Normal file
66
libphobos/testsuite/libphobos.phobos/std_socket.d
Normal file
|
@ -0,0 +1,66 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.socket;
|
||||
|
||||
InternetHost ih = new InternetHost;
|
||||
|
||||
ih.getHostByAddr(0x7F_00_00_01);
|
||||
assert(ih.addrList[0] == 0x7F_00_00_01);
|
||||
ih.getHostByAddr("127.0.0.1");
|
||||
assert(ih.addrList[0] == 0x7F_00_00_01);
|
||||
|
||||
if (!ih.getHostByName("www.digitalmars.com"))
|
||||
return; // don't fail if not connected to internet
|
||||
|
||||
assert(ih.addrList.length);
|
||||
InternetAddress ia = new InternetAddress(ih.addrList[0], InternetAddress.PORT_ANY);
|
||||
assert(ih.name == "www.digitalmars.com" || ih.name == "digitalmars.com",
|
||||
ih.name);
|
||||
|
||||
/* The following assert randomly fails in the test suite.
|
||||
* https://issues.dlang.org/show_bug.cgi?id=22791
|
||||
* So just ignore it when it fails.
|
||||
*/
|
||||
//assert(ih.getHostByAddr(ih.addrList[0]));
|
||||
if (ih.getHostByAddr(ih.addrList[0]))
|
||||
{
|
||||
string getHostNameFromInt = ih.name.dup;
|
||||
|
||||
// This randomly fails in the compiler test suite
|
||||
//assert(ih.getHostByAddr(ia.toAddrString()));
|
||||
|
||||
if (ih.getHostByAddr(ia.toAddrString()))
|
||||
{
|
||||
string getHostNameFromStr = ih.name.dup;
|
||||
assert(getHostNameFromInt == getHostNameFromStr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.socket;
|
||||
|
||||
auto addr1 = new InternetAddress("127.0.0.1", 80);
|
||||
auto addr2 = new InternetAddress("127.0.0.2", 80);
|
||||
|
||||
assert(addr1 == addr1);
|
||||
assert(addr1 != addr2);
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.socket;
|
||||
|
||||
immutable ubyte[4] data = [1, 2, 3, 4];
|
||||
auto pair = socketPair();
|
||||
scope(exit) foreach (s; pair) s.close();
|
||||
|
||||
pair[0].send(data[]);
|
||||
|
||||
auto buf = new ubyte[data.length];
|
||||
pair[1].receive(buf);
|
||||
assert(buf == data);
|
||||
}
|
||||
|
185
libphobos/testsuite/libphobos.phobos/std_stdio.d
Normal file
185
libphobos/testsuite/libphobos.phobos/std_stdio.d
Normal file
|
@ -0,0 +1,185 @@
|
|||
@system unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
static import std.file;
|
||||
|
||||
auto testFile = std.file.deleteme();
|
||||
std.file.write(testFile, "\r\n\n\r\n");
|
||||
scope(exit) std.file.remove(testFile);
|
||||
|
||||
auto f = File(testFile, "r");
|
||||
auto buf = f.rawRead(new char[5]);
|
||||
f.close();
|
||||
assert(buf == "\r\n\n\r\n");
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
static import std.file;
|
||||
|
||||
auto testFile = std.file.deleteme();
|
||||
auto f = File(testFile, "w");
|
||||
scope(exit) std.file.remove(testFile);
|
||||
|
||||
f.rawWrite("\r\n\n\r\n");
|
||||
f.close();
|
||||
assert(std.file.read(testFile) == "\r\n\n\r\n");
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
import std.conv : text;
|
||||
static import std.file;
|
||||
|
||||
auto testFile = std.file.deleteme();
|
||||
std.file.write(testFile, "abcdefghijklmnopqrstuvwqxyz");
|
||||
scope(exit) { std.file.remove(testFile); }
|
||||
|
||||
auto f = File(testFile);
|
||||
auto a = new ubyte[4];
|
||||
f.rawRead(a);
|
||||
assert(f.tell == 4, text(f.tell));
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
static import std.file;
|
||||
|
||||
auto deleteme = std.file.deleteme();
|
||||
std.file.write(deleteme, "hello\nworld\ntrue\nfalse\n");
|
||||
scope(exit) std.file.remove(deleteme);
|
||||
string s;
|
||||
auto f = File(deleteme);
|
||||
f.readf!"%s\n"(s);
|
||||
assert(s == "hello", "["~s~"]");
|
||||
f.readf("%s\n", s);
|
||||
assert(s == "world", "["~s~"]");
|
||||
|
||||
bool b1, b2;
|
||||
f.readf("%s\n%s\n", b1, b2);
|
||||
assert(b1 == true && b2 == false);
|
||||
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
static import std.file;
|
||||
import std.typecons : tuple;
|
||||
|
||||
// prepare test file
|
||||
auto testFile = std.file.deleteme();
|
||||
scope(failure) printf("Failed test at line %d\n", __LINE__);
|
||||
std.file.write(testFile, "1 2\n4 1\n5 100");
|
||||
scope(exit) std.file.remove(testFile);
|
||||
|
||||
File f = File(testFile);
|
||||
scope(exit) f.close();
|
||||
|
||||
auto expected = [tuple(1, 2), tuple(4, 1), tuple(5, 100)];
|
||||
uint i;
|
||||
foreach (e; f.byRecord!(int, int)("%s %s"))
|
||||
{
|
||||
assert(e == expected[i++]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
static assert(isFileHandle!(FILE*));
|
||||
static assert(isFileHandle!(File));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
// Read stdin, sort lines, write to stdout
|
||||
import std.algorithm.mutation : copy;
|
||||
import std.algorithm.sorting : sort;
|
||||
import std.array : array;
|
||||
import std.typecons : Yes;
|
||||
|
||||
void main()
|
||||
{
|
||||
stdin // read from stdin
|
||||
.byLineCopy(Yes.keepTerminator) // copying each line
|
||||
.array() // convert to array of lines
|
||||
.sort() // sort the lines
|
||||
.copy( // copy output of .sort to an OutputRange
|
||||
stdout.lockingTextWriter()); // the OutputRange
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
void main()
|
||||
{
|
||||
stdout.writeln("Write a message to stdout.");
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
void main()
|
||||
{
|
||||
import std.algorithm.iteration : filter, map, sum;
|
||||
import std.format : format;
|
||||
import std.range : iota, tee;
|
||||
|
||||
int len;
|
||||
const r = 6.iota
|
||||
.filter!(a => a % 2) // 1 3 5
|
||||
.map!(a => a * 2) // 2 6 10
|
||||
.tee!(_ => stdout.writefln("len: %d", len++))
|
||||
.sum;
|
||||
|
||||
assert(r == 18);
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
void main()
|
||||
{
|
||||
import std.algorithm.mutation : copy;
|
||||
import std.algorithm.iteration : map;
|
||||
import std.format : format;
|
||||
import std.range : iota;
|
||||
|
||||
10.iota
|
||||
.map!(e => "N: %d".format(e))
|
||||
.copy(stdout.lockingTextWriter()); // the OutputRange
|
||||
}
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.stdio;
|
||||
|
||||
void main()
|
||||
{
|
||||
stderr.writeln("Write a message to stderr.");
|
||||
}
|
||||
}
|
||||
|
892
libphobos/testsuite/libphobos.phobos/std_string.d
Normal file
892
libphobos/testsuite/libphobos.phobos/std_string.d
Normal file
|
@ -0,0 +1,892 @@
|
|||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.exception : assertThrown;
|
||||
auto bad = " a\n\tb\n c";
|
||||
assertThrown!StringException(bad.outdent);
|
||||
}
|
||||
|
||||
@system pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(fromStringz("foo\0"c.ptr) == "foo"c);
|
||||
assert(fromStringz("foo\0"w.ptr) == "foo"w);
|
||||
assert(fromStringz("foo\0"d.ptr) == "foo"d);
|
||||
|
||||
assert(fromStringz("福\0"c.ptr) == "福"c);
|
||||
assert(fromStringz("福\0"w.ptr) == "福"w);
|
||||
assert(fromStringz("福\0"d.ptr) == "福"d);
|
||||
}
|
||||
|
||||
@nogc @safe pure nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
struct C
|
||||
{
|
||||
char[32] name;
|
||||
}
|
||||
assert(C("foo\0"c).name.fromStringz() == "foo"c);
|
||||
|
||||
struct W
|
||||
{
|
||||
wchar[32] name;
|
||||
}
|
||||
assert(W("foo\0"w).name.fromStringz() == "foo"w);
|
||||
|
||||
struct D
|
||||
{
|
||||
dchar[32] name;
|
||||
}
|
||||
assert(D("foo\0"d).name.fromStringz() == "foo"d);
|
||||
}
|
||||
|
||||
pure nothrow @system unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import core.stdc.string : strlen;
|
||||
import std.conv : to;
|
||||
|
||||
auto p = toStringz("foo");
|
||||
assert(strlen(p) == 3);
|
||||
const(char)[] foo = "abbzxyzzy";
|
||||
p = toStringz(foo[3 .. 5]);
|
||||
assert(strlen(p) == 2);
|
||||
|
||||
string test = "";
|
||||
p = toStringz(test);
|
||||
assert(*p == 0);
|
||||
|
||||
test = "\0";
|
||||
p = toStringz(test);
|
||||
assert(*p == 0);
|
||||
|
||||
test = "foo\0";
|
||||
p = toStringz(test);
|
||||
assert(p[0] == 'f' && p[1] == 'o' && p[2] == 'o' && p[3] == 0);
|
||||
|
||||
const string test2 = "";
|
||||
p = toStringz(test2);
|
||||
assert(*p == 0);
|
||||
|
||||
assert(toStringz([]) is toStringz(""));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.typecons : No;
|
||||
|
||||
string s = "Hello World";
|
||||
assert(indexOf(s, 'W') == 6);
|
||||
assert(indexOf(s, 'Z') == -1);
|
||||
assert(indexOf(s, 'w', No.caseSensitive) == 6);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.typecons : No;
|
||||
|
||||
string s = "Hello World";
|
||||
assert(indexOf(s, 'W', 4) == 6);
|
||||
assert(indexOf(s, 'Z', 100) == -1);
|
||||
assert(indexOf(s, 'w', 3, No.caseSensitive) == 6);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.typecons : No;
|
||||
|
||||
string s = "Hello World";
|
||||
assert(indexOf(s, "Wo", 4) == 6);
|
||||
assert(indexOf(s, "Zo", 100) == -1);
|
||||
assert(indexOf(s, "wo", 3, No.caseSensitive) == 6);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.typecons : No;
|
||||
|
||||
string s = "Hello World";
|
||||
assert(indexOf(s, "Wo") == 6);
|
||||
assert(indexOf(s, "Zo") == -1);
|
||||
assert(indexOf(s, "wO", No.caseSensitive) == 6);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.typecons : No;
|
||||
|
||||
string s = "Hello World";
|
||||
assert(lastIndexOf(s, 'l') == 9);
|
||||
assert(lastIndexOf(s, 'Z') == -1);
|
||||
assert(lastIndexOf(s, 'L', No.caseSensitive) == 9);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.typecons : No;
|
||||
|
||||
string s = "Hello World";
|
||||
assert(lastIndexOf(s, 'l', 4) == 3);
|
||||
assert(lastIndexOf(s, 'Z', 1337) == -1);
|
||||
assert(lastIndexOf(s, 'L', 7, No.caseSensitive) == 3);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.typecons : No;
|
||||
|
||||
string s = "Hello World";
|
||||
assert(lastIndexOf(s, "ll") == 2);
|
||||
assert(lastIndexOf(s, "Zo") == -1);
|
||||
assert(lastIndexOf(s, "lL", No.caseSensitive) == 2);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.typecons : No;
|
||||
|
||||
string s = "Hello World";
|
||||
assert(lastIndexOf(s, "ll", 4) == 2);
|
||||
assert(lastIndexOf(s, "Zo", 128) == -1);
|
||||
assert(lastIndexOf(s, "lL", 3, No.caseSensitive) == -1);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.conv : to;
|
||||
|
||||
ptrdiff_t i = "helloWorld".indexOfAny("Wr");
|
||||
assert(i == 5);
|
||||
i = "öällo world".indexOfAny("lo ");
|
||||
assert(i == 4, to!string(i));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.conv : to;
|
||||
|
||||
ptrdiff_t i = "helloWorld".indexOfAny("Wr", 4);
|
||||
assert(i == 5);
|
||||
|
||||
i = "Foo öällo world".indexOfAny("lh", 3);
|
||||
assert(i == 8, to!string(i));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
ptrdiff_t i = "helloWorld".lastIndexOfAny("Wlo");
|
||||
assert(i == 8);
|
||||
|
||||
i = "Foo öäöllo world".lastIndexOfAny("öF");
|
||||
assert(i == 8);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.conv : to;
|
||||
|
||||
ptrdiff_t i = "helloWorld".lastIndexOfAny("Wlo", 4);
|
||||
assert(i == 3);
|
||||
|
||||
i = "Foo öäöllo world".lastIndexOfAny("öF", 3);
|
||||
assert(i == 0);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(indexOfNeither("abba", "a", 2) == 2);
|
||||
assert(indexOfNeither("def", "de", 1) == 2);
|
||||
assert(indexOfNeither("dfefffg", "dfe", 4) == 6);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(indexOfNeither("def", "a") == 0);
|
||||
assert(indexOfNeither("def", "de") == 2);
|
||||
assert(indexOfNeither("dfefffg", "dfe") == 6);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(lastIndexOfNeither("abba", "a") == 2);
|
||||
assert(lastIndexOfNeither("def", "f") == 1);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(lastIndexOfNeither("def", "rsa", 3) == -1);
|
||||
assert(lastIndexOfNeither("abba", "a", 2) == 1);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
string s = "hello";
|
||||
static assert(is(typeof(representation(s)) == immutable(ubyte)[]));
|
||||
assert(representation(s) is cast(immutable(ubyte)[]) s);
|
||||
assert(representation(s) == [0x68, 0x65, 0x6c, 0x6c, 0x6f]);
|
||||
}
|
||||
|
||||
pure @safe unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(capitalize("hello") == "Hello");
|
||||
assert(capitalize("World") == "World");
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
string s = "Hello\nmy\rname\nis";
|
||||
assert(splitLines(s) == ["Hello", "my", "name", "is"]);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.array : array;
|
||||
|
||||
string s = "Hello\nmy\rname\nis";
|
||||
|
||||
/* notice the call to 'array' to turn the lazy range created by
|
||||
lineSplitter comparable to the string[] created by splitLines.
|
||||
*/
|
||||
assert(lineSplitter(s).array == splitLines(s));
|
||||
}
|
||||
|
||||
@nogc @safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
auto s = "\rpeter\n\rpaul\r\njerry\u2028ice\u2029cream\n\nsunday\nmon\u2030day\n";
|
||||
auto lines = s.lineSplitter();
|
||||
static immutable witness = ["", "peter", "", "paul", "jerry", "ice", "cream", "", "sunday", "mon\u2030day"];
|
||||
uint i;
|
||||
foreach (line; lines)
|
||||
{
|
||||
assert(line == witness[i++]);
|
||||
}
|
||||
assert(i == witness.length);
|
||||
}
|
||||
|
||||
nothrow @safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.uni : lineSep, paraSep;
|
||||
assert(stripLeft(" hello world ") ==
|
||||
"hello world ");
|
||||
assert(stripLeft("\n\t\v\rhello world\n\t\v\r") ==
|
||||
"hello world\n\t\v\r");
|
||||
assert(stripLeft(" \u2028hello world") ==
|
||||
"hello world");
|
||||
assert(stripLeft("hello world") ==
|
||||
"hello world");
|
||||
assert(stripLeft([lineSep] ~ "hello world" ~ lineSep) ==
|
||||
"hello world" ~ [lineSep]);
|
||||
assert(stripLeft([paraSep] ~ "hello world" ~ paraSep) ==
|
||||
"hello world" ~ [paraSep]);
|
||||
|
||||
import std.array : array;
|
||||
import std.utf : byChar;
|
||||
assert(stripLeft(" hello world "w.byChar).array ==
|
||||
"hello world ");
|
||||
assert(stripLeft(" \u2022hello world ".byChar).array ==
|
||||
"\u2022hello world ");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(stripLeft(" hello world ", " ") ==
|
||||
"hello world ");
|
||||
assert(stripLeft("xxxxxhello world ", "x") ==
|
||||
"hello world ");
|
||||
assert(stripLeft("xxxyy hello world ", "xy ") ==
|
||||
"hello world ");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.array : array;
|
||||
import std.utf : byChar, byWchar, byDchar;
|
||||
|
||||
assert(stripLeft(" xxxyy hello world "w.byChar, "xy ").array ==
|
||||
"hello world ");
|
||||
|
||||
assert(stripLeft("\u2028\u2020hello world\u2028"w.byWchar,
|
||||
"\u2028").array == "\u2020hello world\u2028");
|
||||
assert(stripLeft("\U00010001hello world"w.byWchar, " ").array ==
|
||||
"\U00010001hello world"w);
|
||||
assert(stripLeft("\U00010001 xyhello world"d.byDchar,
|
||||
"\U00010001 xy").array == "hello world"d);
|
||||
|
||||
assert(stripLeft("\u2020hello"w, "\u2020"w) == "hello"w);
|
||||
assert(stripLeft("\U00010001hello"d, "\U00010001"d) == "hello"d);
|
||||
assert(stripLeft(" hello ", "") == " hello ");
|
||||
}
|
||||
|
||||
nothrow @safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.uni : lineSep, paraSep;
|
||||
assert(stripRight(" hello world ") ==
|
||||
" hello world");
|
||||
assert(stripRight("\n\t\v\rhello world\n\t\v\r") ==
|
||||
"\n\t\v\rhello world");
|
||||
assert(stripRight("hello world") ==
|
||||
"hello world");
|
||||
assert(stripRight([lineSep] ~ "hello world" ~ lineSep) ==
|
||||
[lineSep] ~ "hello world");
|
||||
assert(stripRight([paraSep] ~ "hello world" ~ paraSep) ==
|
||||
[paraSep] ~ "hello world");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(stripRight(" hello world ", "x") ==
|
||||
" hello world ");
|
||||
assert(stripRight(" hello world ", " ") ==
|
||||
" hello world");
|
||||
assert(stripRight(" hello worldxy ", "xy ") ==
|
||||
" hello world");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.uni : lineSep, paraSep;
|
||||
assert(strip(" hello world ") ==
|
||||
"hello world");
|
||||
assert(strip("\n\t\v\rhello world\n\t\v\r") ==
|
||||
"hello world");
|
||||
assert(strip("hello world") ==
|
||||
"hello world");
|
||||
assert(strip([lineSep] ~ "hello world" ~ [lineSep]) ==
|
||||
"hello world");
|
||||
assert(strip([paraSep] ~ "hello world" ~ [paraSep]) ==
|
||||
"hello world");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(strip(" hello world ", "x") ==
|
||||
" hello world ");
|
||||
assert(strip(" hello world ", " ") ==
|
||||
"hello world");
|
||||
assert(strip(" xyxyhello worldxyxy ", "xy ") ==
|
||||
"hello world");
|
||||
assert(strip("\u2020hello\u2020"w, "\u2020"w) == "hello"w);
|
||||
assert(strip("\U00010001hello\U00010001"d, "\U00010001"d) == "hello"d);
|
||||
assert(strip(" hello ", "") == " hello ");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(strip("xxhelloyy", "x", "y") == "hello");
|
||||
assert(strip(" xyxyhello worldxyxyzz ", "xy ", "xyz ") ==
|
||||
"hello world");
|
||||
assert(strip("\u2020hello\u2028"w, "\u2020"w, "\u2028"w) == "hello"w);
|
||||
assert(strip("\U00010001hello\U00010002"d, "\U00010001"d, "\U00010002"d) ==
|
||||
"hello"d);
|
||||
assert(strip(" hello ", "", "") == " hello ");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.uni : lineSep, paraSep, nelSep;
|
||||
import std.utf : decode;
|
||||
assert(chomp(" hello world \n\r") == " hello world \n");
|
||||
assert(chomp(" hello world \r\n") == " hello world ");
|
||||
assert(chomp(" hello world \f") == " hello world ");
|
||||
assert(chomp(" hello world \v") == " hello world ");
|
||||
assert(chomp(" hello world \n\n") == " hello world \n");
|
||||
assert(chomp(" hello world \n\n ") == " hello world \n\n ");
|
||||
assert(chomp(" hello world \n\n" ~ [lineSep]) == " hello world \n\n");
|
||||
assert(chomp(" hello world \n\n" ~ [paraSep]) == " hello world \n\n");
|
||||
assert(chomp(" hello world \n\n" ~ [ nelSep]) == " hello world \n\n");
|
||||
assert(chomp(" hello world ") == " hello world ");
|
||||
assert(chomp(" hello world") == " hello world");
|
||||
assert(chomp("") == "");
|
||||
|
||||
assert(chomp(" hello world", "orld") == " hello w");
|
||||
assert(chomp(" hello world", " he") == " hello world");
|
||||
assert(chomp("", "hello") == "");
|
||||
|
||||
// Don't decode pointlessly
|
||||
assert(chomp("hello\xFE", "\r") == "hello\xFE");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(chompPrefix("hello world", "he") == "llo world");
|
||||
assert(chompPrefix("hello world", "hello w") == "orld");
|
||||
assert(chompPrefix("hello world", " world") == "hello world");
|
||||
assert(chompPrefix("", "hello") == "");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(chop("hello world") == "hello worl");
|
||||
assert(chop("hello world\n") == "hello world");
|
||||
assert(chop("hello world\r") == "hello world");
|
||||
assert(chop("hello world\n\r") == "hello world\n");
|
||||
assert(chop("hello world\r\n") == "hello world");
|
||||
assert(chop("Walter Bright") == "Walter Brigh");
|
||||
assert(chop("") == "");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(leftJustify("hello", 7, 'X') == "helloXX");
|
||||
assert(leftJustify("hello", 2, 'X') == "hello");
|
||||
assert(leftJustify("hello", 9, 'X') == "helloXXXX");
|
||||
}
|
||||
|
||||
@safe pure @nogc nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.utf : byChar;
|
||||
assert(leftJustifier("hello", 2).equal("hello".byChar));
|
||||
assert(leftJustifier("hello", 7).equal("hello ".byChar));
|
||||
assert(leftJustifier("hello", 7, 'x').equal("helloxx".byChar));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(rightJustify("hello", 7, 'X') == "XXhello");
|
||||
assert(rightJustify("hello", 2, 'X') == "hello");
|
||||
assert(rightJustify("hello", 9, 'X') == "XXXXhello");
|
||||
}
|
||||
|
||||
@safe pure @nogc nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.utf : byChar;
|
||||
assert(rightJustifier("hello", 2).equal("hello".byChar));
|
||||
assert(rightJustifier("hello", 7).equal(" hello".byChar));
|
||||
assert(rightJustifier("hello", 7, 'x').equal("xxhello".byChar));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(center("hello", 7, 'X') == "XhelloX");
|
||||
assert(center("hello", 2, 'X') == "hello");
|
||||
assert(center("hello", 9, 'X') == "XXhelloXX");
|
||||
}
|
||||
|
||||
@safe pure @nogc nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.algorithm.comparison : equal;
|
||||
import std.utf : byChar;
|
||||
assert(centerJustifier("hello", 2).equal("hello".byChar));
|
||||
assert(centerJustifier("hello", 8).equal(" hello ".byChar));
|
||||
assert(centerJustifier("hello", 7, 'x').equal("xhellox".byChar));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(detab(" \n\tx", 9) == " \n x");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.array : array;
|
||||
|
||||
assert(detabber(" \n\tx", 9).array == " \n x");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.array : array;
|
||||
import std.utf : byChar, byWchar;
|
||||
|
||||
assert(detabber(" \u2029\t".byChar, 9).array == " \u2029 ");
|
||||
auto r = "hel\tx".byWchar.detabber();
|
||||
assert(r.front == 'h');
|
||||
auto s = r.save;
|
||||
r.popFront();
|
||||
r.popFront();
|
||||
assert(r.front == 'l');
|
||||
assert(s.front == 'h');
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(entab(" x \n") == "\tx\n");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.array : array;
|
||||
assert(entabber(" x \n").array == "\tx\n");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
dchar[dchar] transTable1 = ['e' : '5', 'o' : '7', '5': 'q'];
|
||||
assert(translate("hello world", transTable1) == "h5ll7 w7rld");
|
||||
|
||||
assert(translate("hello world", transTable1, "low") == "h5 rd");
|
||||
|
||||
string[dchar] transTable2 = ['e' : "5", 'o' : "orange"];
|
||||
assert(translate("hello world", transTable2) == "h5llorange worangerld");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.array : appender;
|
||||
dchar[dchar] transTable1 = ['e' : '5', 'o' : '7', '5': 'q'];
|
||||
auto buffer = appender!(dchar[])();
|
||||
translate("hello world", transTable1, null, buffer);
|
||||
assert(buffer.data == "h5ll7 w7rld");
|
||||
|
||||
buffer.clear();
|
||||
translate("hello world", transTable1, "low", buffer);
|
||||
assert(buffer.data == "h5 rd");
|
||||
|
||||
buffer.clear();
|
||||
string[dchar] transTable2 = ['e' : "5", 'o' : "orange"];
|
||||
translate("hello world", transTable2, null, buffer);
|
||||
assert(buffer.data == "h5llorange worangerld");
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
auto transTable1 = makeTrans("eo5", "57q");
|
||||
assert(translate("hello world", transTable1) == "h5ll7 w7rld");
|
||||
|
||||
assert(translate("hello world", transTable1, "low") == "h5 rd");
|
||||
}
|
||||
|
||||
@safe pure nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
auto transTable1 = makeTrans("eo5", "57q");
|
||||
assert(translate("hello world", transTable1) == "h5ll7 w7rld");
|
||||
|
||||
assert(translate("hello world", transTable1, "low") == "h5 rd");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(translate("hello world", makeTransTable("hl", "q5")) == "qe55o wor5d");
|
||||
assert(translate("hello world", makeTransTable("12345", "67890")) == "hello world");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.array : appender;
|
||||
auto buffer = appender!(char[])();
|
||||
auto transTable1 = makeTransTable("eo5", "57q");
|
||||
translate("hello world", transTable1, null, buffer);
|
||||
assert(buffer.data == "h5ll7 w7rld");
|
||||
|
||||
buffer.clear();
|
||||
translate("hello world", transTable1, "low", buffer);
|
||||
assert(buffer.data == "h5 rd");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(succ("1") == "2");
|
||||
assert(succ("9") == "10");
|
||||
assert(succ("999") == "1000");
|
||||
assert(succ("zz99") == "aaa00");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(tr("abcdef", "cd", "CD") == "abCDef");
|
||||
assert(tr("1st March, 2018", "March", "MAR", "s") == "1st MAR, 2018");
|
||||
assert(tr("abcdef", "ef", "", "d") == "abcd");
|
||||
assert(tr("14-Jul-87", "a-zA-Z", " ", "cs") == " Jul ");
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(isNumeric("123"));
|
||||
assert(isNumeric("123UL"));
|
||||
assert(isNumeric("123L"));
|
||||
assert(isNumeric("+123U"));
|
||||
assert(isNumeric("-123L"));
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(isNumeric("+123"));
|
||||
assert(isNumeric("-123.01"));
|
||||
assert(isNumeric("123.3e-10f"));
|
||||
assert(isNumeric("123.3e-10fi"));
|
||||
assert(isNumeric("123.3e-10L"));
|
||||
|
||||
assert(isNumeric("nan"));
|
||||
assert(isNumeric("nani"));
|
||||
assert(isNumeric("-inf"));
|
||||
}
|
||||
|
||||
@safe @nogc pure nothrow unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(isNumeric("-123e-1+456.9e-10Li"));
|
||||
assert(isNumeric("+123e+10+456i"));
|
||||
assert(isNumeric("123+456"));
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
enum a = isNumeric("123.00E-5+1234.45E-12Li");
|
||||
enum b = isNumeric("12345xxxx890");
|
||||
|
||||
static assert( a);
|
||||
static assert(!b);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(soundexer("Gauss") == "G200");
|
||||
assert(soundexer("Ghosh") == "G200");
|
||||
|
||||
assert(soundexer("Robert") == "R163");
|
||||
assert(soundexer("Rupert") == "R163");
|
||||
|
||||
assert(soundexer("0123^&^^**&^") == ['\0', '\0', '\0', '\0']);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(soundex("Gauss") == "G200");
|
||||
assert(soundex("Ghosh") == "G200");
|
||||
|
||||
assert(soundex("Robert") == "R163");
|
||||
assert(soundex("Rupert") == "R163");
|
||||
|
||||
assert(soundex("0123^&^^**&^") == null);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.string;
|
||||
|
||||
static string[] list = [ "food", "foxy" ];
|
||||
auto abbrevs = abbrev(list);
|
||||
assert(abbrevs == ["fox": "foxy", "food": "food",
|
||||
"foxy": "foxy", "foo": "food"]);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
import std.utf : byChar, byWchar, byDchar;
|
||||
|
||||
assert(column("1234 ") == 5);
|
||||
assert(column("1234 "w) == 5);
|
||||
assert(column("1234 "d) == 5);
|
||||
|
||||
assert(column("1234 ".byChar()) == 5);
|
||||
assert(column("1234 "w.byWchar()) == 5);
|
||||
assert(column("1234 "d.byDchar()) == 5);
|
||||
|
||||
// Tab stops are set at 8 spaces by default; tab characters insert enough
|
||||
// spaces to bring the column position to the next multiple of 8.
|
||||
assert(column("\t") == 8);
|
||||
assert(column("1\t") == 8);
|
||||
assert(column("\t1") == 9);
|
||||
assert(column("123\t") == 8);
|
||||
|
||||
// Other tab widths are possible by specifying it explicitly:
|
||||
assert(column("\t", 4) == 4);
|
||||
assert(column("1\t", 4) == 4);
|
||||
assert(column("\t1", 4) == 5);
|
||||
assert(column("123\t", 4) == 4);
|
||||
|
||||
// New lines reset the column number.
|
||||
assert(column("abc\n") == 0);
|
||||
assert(column("abc\n1") == 1);
|
||||
assert(column("abcdefg\r1234") == 4);
|
||||
assert(column("abc\u20281") == 1);
|
||||
assert(column("abc\u20291") == 1);
|
||||
assert(column("abc\u00851") == 1);
|
||||
assert(column("abc\u00861") == 5);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
assert(wrap("a short string", 7) == "a short\nstring\n");
|
||||
|
||||
// wrap will not break inside of a word, but at the next space
|
||||
assert(wrap("a short string", 4) == "a\nshort\nstring\n");
|
||||
|
||||
assert(wrap("a short string", 7, "\t") == "\ta\nshort\nstring\n");
|
||||
assert(wrap("a short string", 7, "\t", " ") == "\ta\n short\n string\n");
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
enum pretty = q{
|
||||
import std.stdio;
|
||||
void main() {
|
||||
writeln("Hello");
|
||||
}
|
||||
}.outdent();
|
||||
|
||||
enum ugly = q{
|
||||
import std.stdio;
|
||||
void main() {
|
||||
writeln("Hello");
|
||||
}
|
||||
};
|
||||
|
||||
assert(pretty == ugly);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
auto str1 = [
|
||||
" void main()\n",
|
||||
" {\n",
|
||||
" test();\n",
|
||||
" }\n"
|
||||
];
|
||||
auto str1Expected = [
|
||||
"void main()\n",
|
||||
"{\n",
|
||||
" test();\n",
|
||||
"}\n"
|
||||
];
|
||||
assert(str1.outdent == str1Expected);
|
||||
|
||||
auto str2 = [
|
||||
"void main()\n",
|
||||
" {\n",
|
||||
" test();\n",
|
||||
" }\n"
|
||||
];
|
||||
assert(str2.outdent == str2);
|
||||
}
|
||||
|
||||
@safe pure unittest
|
||||
{
|
||||
import std.string;
|
||||
|
||||
string a = "Hölo World";
|
||||
immutable(ubyte)[] b = a.representation;
|
||||
string c = b.assumeUTF;
|
||||
|
||||
assert(c == "Hölo World");
|
||||
}
|
||||
|
301
libphobos/testsuite/libphobos.phobos/std_sumtype.d
Normal file
301
libphobos/testsuite/libphobos.phobos/std_sumtype.d
Normal file
|
@ -0,0 +1,301 @@
|
|||
@safe unittest
|
||||
{
|
||||
import std.sumtype;
|
||||
|
||||
import std.math.operations : isClose;
|
||||
|
||||
struct Fahrenheit { double degrees; }
|
||||
struct Celsius { double degrees; }
|
||||
struct Kelvin { double degrees; }
|
||||
|
||||
alias Temperature = SumType!(Fahrenheit, Celsius, Kelvin);
|
||||
|
||||
// Construct from any of the member types.
|
||||
Temperature t1 = Fahrenheit(98.6);
|
||||
Temperature t2 = Celsius(100);
|
||||
Temperature t3 = Kelvin(273);
|
||||
|
||||
// Use pattern matching to access the value.
|
||||
Fahrenheit toFahrenheit(Temperature t)
|
||||
{
|
||||
return Fahrenheit(
|
||||
t.match!(
|
||||
(Fahrenheit f) => f.degrees,
|
||||
(Celsius c) => c.degrees * 9.0/5 + 32,
|
||||
(Kelvin k) => k.degrees * 9.0/5 - 459.4
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
assert(toFahrenheit(t1).degrees.isClose(98.6));
|
||||
assert(toFahrenheit(t2).degrees.isClose(212));
|
||||
assert(toFahrenheit(t3).degrees.isClose(32));
|
||||
|
||||
// Use ref to modify the value in place.
|
||||
void freeze(ref Temperature t)
|
||||
{
|
||||
t.match!(
|
||||
(ref Fahrenheit f) => f.degrees = 32,
|
||||
(ref Celsius c) => c.degrees = 0,
|
||||
(ref Kelvin k) => k.degrees = 273
|
||||
);
|
||||
}
|
||||
|
||||
freeze(t1);
|
||||
assert(toFahrenheit(t1).degrees.isClose(32));
|
||||
|
||||
// Use a catch-all handler to give a default result.
|
||||
bool isFahrenheit(Temperature t)
|
||||
{
|
||||
return t.match!(
|
||||
(Fahrenheit f) => true,
|
||||
_ => false
|
||||
);
|
||||
}
|
||||
|
||||
assert(isFahrenheit(t1));
|
||||
assert(!isFahrenheit(t2));
|
||||
assert(!isFahrenheit(t3));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.sumtype;
|
||||
|
||||
alias ExampleSumType = SumType!(int, string, double);
|
||||
|
||||
ExampleSumType a = 123;
|
||||
ExampleSumType b = "hello";
|
||||
ExampleSumType c = 3.14;
|
||||
|
||||
assert(a.handle == "got an int");
|
||||
assert(b.handle == "got a string");
|
||||
assert(c.handle == "got a double");
|
||||
}
|
||||
|
||||
@system unittest
|
||||
{
|
||||
import std.sumtype;
|
||||
|
||||
import std.functional : partial;
|
||||
import std.traits : EnumMembers;
|
||||
import std.typecons : Tuple;
|
||||
|
||||
enum Op : string
|
||||
{
|
||||
Plus = "+",
|
||||
Minus = "-",
|
||||
Times = "*",
|
||||
Div = "/"
|
||||
}
|
||||
|
||||
// An expression is either
|
||||
// - a number,
|
||||
// - a variable, or
|
||||
// - a binary operation combining two sub-expressions.
|
||||
alias Expr = SumType!(
|
||||
double,
|
||||
string,
|
||||
Tuple!(Op, "op", This*, "lhs", This*, "rhs")
|
||||
);
|
||||
|
||||
// Shorthand for Tuple!(Op, "op", Expr*, "lhs", Expr*, "rhs"),
|
||||
// the Tuple type above with Expr substituted for This.
|
||||
alias BinOp = Expr.Types[2];
|
||||
|
||||
// Factory function for number expressions
|
||||
Expr* num(double value)
|
||||
{
|
||||
return new Expr(value);
|
||||
}
|
||||
|
||||
// Factory function for variable expressions
|
||||
Expr* var(string name)
|
||||
{
|
||||
return new Expr(name);
|
||||
}
|
||||
|
||||
// Factory function for binary operation expressions
|
||||
Expr* binOp(Op op, Expr* lhs, Expr* rhs)
|
||||
{
|
||||
return new Expr(BinOp(op, lhs, rhs));
|
||||
}
|
||||
|
||||
// Convenience wrappers for creating BinOp expressions
|
||||
alias sum = partial!(binOp, Op.Plus);
|
||||
alias diff = partial!(binOp, Op.Minus);
|
||||
alias prod = partial!(binOp, Op.Times);
|
||||
alias quot = partial!(binOp, Op.Div);
|
||||
|
||||
// Evaluate expr, looking up variables in env
|
||||
double eval(Expr expr, double[string] env)
|
||||
{
|
||||
return expr.match!(
|
||||
(double num) => num,
|
||||
(string var) => env[var],
|
||||
(BinOp bop)
|
||||
{
|
||||
double lhs = eval(*bop.lhs, env);
|
||||
double rhs = eval(*bop.rhs, env);
|
||||
final switch (bop.op)
|
||||
{
|
||||
static foreach (op; EnumMembers!Op)
|
||||
{
|
||||
case op:
|
||||
return mixin("lhs" ~ op ~ "rhs");
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
// Return a "pretty-printed" representation of expr
|
||||
string pprint(Expr expr)
|
||||
{
|
||||
import std.format : format;
|
||||
|
||||
return expr.match!(
|
||||
(double num) => "%g".format(num),
|
||||
(string var) => var,
|
||||
(BinOp bop) => "(%s %s %s)".format(
|
||||
pprint(*bop.lhs),
|
||||
cast(string) bop.op,
|
||||
pprint(*bop.rhs)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
Expr* myExpr = sum(var("a"), prod(num(2), var("b")));
|
||||
double[string] myEnv = ["a":3, "b":4, "c":7];
|
||||
|
||||
assert(eval(*myExpr, myEnv) == 11);
|
||||
assert(pprint(*myExpr) == "(a + (2 * b))");
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.sumtype;
|
||||
|
||||
static struct ConvertsToSumType
|
||||
{
|
||||
SumType!int payload;
|
||||
alias payload this;
|
||||
}
|
||||
|
||||
static struct ContainsSumType
|
||||
{
|
||||
SumType!int payload;
|
||||
}
|
||||
|
||||
assert(isSumType!(SumType!int));
|
||||
assert(isSumType!ConvertsToSumType);
|
||||
assert(!isSumType!ContainsSumType);
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.sumtype;
|
||||
|
||||
alias Number = SumType!(double, int);
|
||||
|
||||
Number x;
|
||||
|
||||
// Problem: because int implicitly converts to double, the double
|
||||
// handler is used for both types, and the int handler never matches.
|
||||
assert(!__traits(compiles,
|
||||
x.match!(
|
||||
(double d) => "got double",
|
||||
(int n) => "got int"
|
||||
)
|
||||
));
|
||||
|
||||
// Solution 1: put the handler for the "more specialized" type (in this
|
||||
// case, int) before the handler for the type it converts to.
|
||||
assert(__traits(compiles,
|
||||
x.match!(
|
||||
(int n) => "got int",
|
||||
(double d) => "got double"
|
||||
)
|
||||
));
|
||||
|
||||
// Solution 2: use a template that only accepts the exact type it's
|
||||
// supposed to match, instead of any type that implicitly converts to it.
|
||||
alias exactly(T, alias fun) = function (arg)
|
||||
{
|
||||
static assert(is(typeof(arg) == T));
|
||||
return fun(arg);
|
||||
};
|
||||
|
||||
// Now, even if we put the double handler first, it will only be used for
|
||||
// doubles, not ints.
|
||||
assert(__traits(compiles,
|
||||
x.match!(
|
||||
exactly!(double, d => "got double"),
|
||||
exactly!(int, n => "got int")
|
||||
)
|
||||
));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.sumtype;
|
||||
|
||||
struct Point2D { double x, y; }
|
||||
struct Point3D { double x, y, z; }
|
||||
|
||||
alias Point = SumType!(Point2D, Point3D);
|
||||
|
||||
version (none)
|
||||
{
|
||||
// This function works, but the code is ugly and repetitive.
|
||||
// It uses three separate calls to match!
|
||||
@safe pure nothrow @nogc
|
||||
bool sameDimensions(Point p1, Point p2)
|
||||
{
|
||||
return p1.match!(
|
||||
(Point2D _) => p2.match!(
|
||||
(Point2D _) => true,
|
||||
_ => false
|
||||
),
|
||||
(Point3D _) => p2.match!(
|
||||
(Point3D _) => true,
|
||||
_ => false
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// This version is much nicer.
|
||||
@safe pure nothrow @nogc
|
||||
bool sameDimensions(Point p1, Point p2)
|
||||
{
|
||||
alias doMatch = match!(
|
||||
(Point2D _1, Point2D _2) => true,
|
||||
(Point3D _1, Point3D _2) => true,
|
||||
(_1, _2) => false
|
||||
);
|
||||
|
||||
return doMatch(p1, p2);
|
||||
}
|
||||
|
||||
Point a = Point2D(1, 2);
|
||||
Point b = Point2D(3, 4);
|
||||
Point c = Point3D(5, 6, 7);
|
||||
Point d = Point3D(8, 9, 0);
|
||||
|
||||
assert( sameDimensions(a, b));
|
||||
assert( sameDimensions(c, d));
|
||||
assert(!sameDimensions(a, c));
|
||||
assert(!sameDimensions(d, b));
|
||||
}
|
||||
|
||||
@safe unittest
|
||||
{
|
||||
import std.sumtype;
|
||||
|
||||
alias handleInt = (int i) => "got an int";
|
||||
|
||||
assert( canMatch!(handleInt, int));
|
||||
assert(!canMatch!(handleInt, string));
|
||||
}
|
||||
|
2419
libphobos/testsuite/libphobos.phobos/std_traits.d
Normal file
2419
libphobos/testsuite/libphobos.phobos/std_traits.d
Normal file
File diff suppressed because it is too large
Load diff
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue