Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .dscanner.ini
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ exception_check="-std.concurrency,-std.net.curl,-std.parallelism,-std.range,-std
; Checks for poor placement of function attributes
function_attribute_check="-std.algorithm.iteration,-std.concurrency,-std.conv,-std.datetime.interval,-std.exception,-std.functional,-std.net.curl,-std.numeric,-std.parallelism,-std.random,-std.range,-std.range.primitives,-std.socket,-std.traits,-std.typecons,-std.uni"
; Check for public declarations without a documented unittest
has_public_example="-etc.c.curl,-etc.c.sqlite3,-etc.c.zlib,-std.algorithm.comparison,-std.algorithm.mutation,-std.array,-std.ascii,-std.base64,-std.bitmanip,-std.complex,-std.concurrency,-std.container.array,-std.container.dlist,-std.container.rbtree,-std.container.slist,-std.conv,-std.csv,-std.datetime,-std.datetime.date,-std.datetime.interval,-std.datetime.stopwatch,-std.datetime.systime,-std.datetime.timezone,-std.demangle,-std.digest.digest,-std.digest.hmac,-std.digest.murmurhash,-std.digest.sha,-std.encoding,-std.exception,-std.experimental.allocator,-std.experimental.allocator.building_blocks.allocator_list,-std.experimental.allocator.building_blocks.bitmapped_block,-std.experimental.allocator.building_blocks.fallback_allocator,-std.experimental.allocator.building_blocks.free_list,-std.experimental.allocator.building_blocks.free_tree,-std.experimental.allocator.building_blocks.null_allocator,-std.experimental.allocator.building_blocks.stats_collector,-std.experimental.allocator.common,-std.experimental.allocator.mmap_allocator,-std.experimental.allocator.typed,-std.experimental.checkedint,-std.experimental.logger.core,-std.experimental.logger.filelogger,-std.experimental.logger.multilogger,-std.experimental.typecons,-std.file,-std.format,-std.getopt,-std.internal.math.biguintcore,-std.internal.math.biguintnoasm,-std.internal.math.errorfunction,-std.internal.math.gammafunction,-std.internal.scopebuffer,-std.internal.test.dummyrange,-std.json,-std.math,-std.mathspecial,-std.mmfile,-std.net.curl,-std.net.isemail,-std.numeric,-std.outbuffer,-std.parallelism,-std.path,-std.process,-std.random,-std.range,-std.range.interfaces,-std.range.primitives,-std.regex,-std.regex.internal.ir,-std.socket,-std.stdio,-std.string,-std.traits,-std.typecons,-std.uni,-std.uri,-std.utf,-std.uuid,-std.variant,-std.xml,-std.zip,-std.zlib"
has_public_example="-etc.c.curl,-etc.c.sqlite3,-etc.c.zlib,-std.bitmanip,-std.complex,-std.concurrency,-std.container.array,-std.container.dlist,-std.container.rbtree,-std.container.slist,-std.conv,-std.csv,-std.datetime,-std.datetime.date,-std.datetime.interval,-std.datetime.stopwatch,-std.datetime.systime,-std.datetime.timezone,-std.demangle,-std.digest.digest,-std.digest.hmac,-std.digest.murmurhash,-std.digest.sha,-std.encoding,-std.exception,-std.experimental.allocator,-std.experimental.allocator.building_blocks.allocator_list,-std.experimental.allocator.building_blocks.bitmapped_block,-std.experimental.allocator.building_blocks.fallback_allocator,-std.experimental.allocator.building_blocks.free_list,-std.experimental.allocator.building_blocks.free_tree,-std.experimental.allocator.building_blocks.null_allocator,-std.experimental.allocator.building_blocks.stats_collector,-std.experimental.allocator.common,-std.experimental.allocator.mmap_allocator,-std.experimental.allocator.typed,-std.experimental.checkedint,-std.experimental.logger.core,-std.experimental.logger.filelogger,-std.experimental.logger.multilogger,-std.experimental.typecons,-std.file,-std.format,-std.getopt,-std.internal.math.biguintcore,-std.internal.math.biguintnoasm,-std.internal.math.errorfunction,-std.internal.math.gammafunction,-std.internal.scopebuffer,-std.internal.test.dummyrange,-std.json,-std.math,-std.mathspecial,-std.mmfile,-std.net.curl,-std.net.isemail,-std.numeric,-std.outbuffer,-std.parallelism,-std.path,-std.process,-std.random,-std.range,-std.range.interfaces,-std.range.primitives,-std.regex,-std.regex.internal.ir,-std.socket,-std.stdio,-std.string,-std.traits,-std.typecons,-std.uni,-std.uri,-std.utf,-std.uuid,-std.variant,-std.xml,-std.zip,-std.zlib"
Copy link
Member

@MetaLang MetaLang Jul 9, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wish we could generate this list manually automatically.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI the list was generated automatically: #5501 - just reducing it isn't automated :/

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Whoops, I just realized I wrote manually by mistake. At least the generating part works so we're not too bad off.

; Check for sortedness of imports
imports_sortedness="+disabled"
;imports_sortedness="-etc.c.curl,-std.algorithm.comparison,-std.algorithm.internal,-std.algorithm.iteration,-std.algorithm.mutation,-std.algorithm.searching,-std.algorithm.setops,-std.algorithm.sorting,-std.array,-std.bigint,-std.bitmanip,-std.c.freebsd.socket,-std.c.linux.pthread,-std.c.process,-std.complex,-std.concurrency,-std.container.array,-std.container.binaryheap,-std.container.dlist,-std.container.rbtree,-std.container.slist,-std.container.util,-std.conv,-std.datetime,-std.datetime.date,-std.datetime.interval,-std.datetime.systime,-std.datetime.timezone,-std.digest.digest,-std.digest.hmac,-std.exception,-std.experimental.allocator,-std.experimental.allocator.building_blocks,-std.experimental.allocator.building_blocks.affix_allocator,-std.experimental.allocator.building_blocks.allocator_list,-std.experimental.allocator.building_blocks.free_list,-std.experimental.allocator.building_blocks.free_tree,-std.experimental.allocator.building_blocks.kernighan_ritchie,-std.experimental.allocator.building_blocks.region,-std.experimental.allocator.common,-std.experimental.allocator.mallocator,-std.experimental.allocator.mmap_allocator,-std.experimental.allocator.showcase,-std.experimental.allocator.typed,-std.experimental.checkedint,-std.experimental.logger.core,-std.experimental.typecons,-std.file,-std.format,-std.functional,-std.getopt,-std.internal.math.biguintcore,-std.internal.test.dummyrange,-std.json,-std.math,-std.meta,-std.mmfile,-std.net.curl,-std.net.isemail,-std.numeric,-std.outbuffer,-std.parallelism,-std.path,-std.process,-std.random,-std.range,-std.range.primitives,-std.regex,-std.regex.internal.backtracking,-std.regex.internal.generator,-std.regex.internal.kickstart,-std.regex.internal.parser,-std.regex.internal.tests,-std.signals,-std.socket,-std.stdio,-std.string,-std.uni,-std.utf,-std.uuid,-std.variant,-std.windows.charset,-std.windows.registry,-std.windows.syserror,-std.zip"
Expand Down
10 changes: 10 additions & 0 deletions std/algorithm/comparison.d
Original file line number Diff line number Diff line change
Expand Up @@ -1007,6 +1007,16 @@ enum EditOp : char
remove = 'r'
}

///
@safe unittest
{
with(EditOp)
{
assert(levenshteinDistanceAndPath("foo", "foobar")[1] == [none, none, none, insert, insert, insert]);
assert(levenshteinDistanceAndPath("banana", "fazan")[1] == [substitute, none, substitute, none, none, remove]);
}
}

private struct Levenshtein(Range, alias equals, CostType = size_t)
{
EditOp[] path()
Expand Down
30 changes: 30 additions & 0 deletions std/algorithm/mutation.d
Original file line number Diff line number Diff line change
Expand Up @@ -1659,6 +1659,36 @@ enum SwapStrategy
stable,
}

///
@safe unittest
{
import std.stdio;
import std.algorithm.sorting : partition;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you import "partition"?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No particular reason except for copy/pasting from the test below :/

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.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]);
}

/**
Eliminates elements at given offsets from `range` and returns the shortened
range.
Expand Down
88 changes: 87 additions & 1 deletion std/array.d
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,18 @@ if (isNarrowString!String)
return cast(typeof(return)) str.toUTF32;
}

///
@safe unittest
{
import std.range.primitives : isRandomAccessRange;

assert("Hello D".array == "Hello D"d);
static assert(isRandomAccessRange!string == false);

assert("Hello D"w.array == "Hello D"d);
static assert(isRandomAccessRange!dstring == true);
}

@system unittest
{
// @system due to array!string
Expand Down Expand Up @@ -534,7 +546,7 @@ if (isDynamicArray!T && allSatisfy!(isIntegral, I) && hasIndirections!(ElementEn
return arrayAllocImpl!(false, T, ST)(sizes);
}

///
/// ditto
auto uninitializedArray(T, I...)(I sizes) nothrow @trusted
if (isDynamicArray!T && allSatisfy!(isIntegral, I) && !hasIndirections!(ElementEncodingType!T))
{
Expand Down Expand Up @@ -588,6 +600,18 @@ if (isDynamicArray!T && allSatisfy!(isIntegral, I))
return arrayAllocImpl!(true, T, ST)(sizes);
}

///
@safe pure nothrow unittest
{
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
assert(!arr.equal(0.repeat(42)));
}

@safe pure nothrow unittest
{
cast(void) minimallyInitializedArray!(int[][][][][])();
Expand Down Expand Up @@ -1535,6 +1559,15 @@ if (isForwardRange!Range && is(typeof(unaryFun!isTerminator(range.front))))
return range.splitter!isTerminator.array;
}

///
@safe unittest
{
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.algorithm.comparison : cmp;
Expand Down Expand Up @@ -3212,6 +3245,23 @@ if (isDynamicArray!A)
}
}

///
@system pure nothrow
unittest
{
int[] a = [1, 2];
auto app2 = appender(&a);
assert(app2.data == [1, 2]);
assert(a == [1, 2]);
app2 ~= 3;
app2 ~= [4, 5, 6];
assert(app2.data == [1, 2, 3, 4, 5, 6]);
assert(a == [1, 2, 3, 4, 5, 6]);

app2.reserve(5);
assert(app2.capacity >= 5);
}

/++
Convenience function that returns an $(LREF Appender) instance,
optionally initialized with $(D array).
Expand Down Expand Up @@ -3334,6 +3384,25 @@ Appender!(E[]) appender(A : E[], E)(auto ref A array)
});
}

///
@safe pure nothrow
unittest
{
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.data == "abcdef");
}

@safe pure nothrow unittest
{
{
Expand Down Expand Up @@ -3597,6 +3666,23 @@ RefAppender!(E[]) appender(P : E[]*, E)(P arrayPtr)
return RefAppender!(E[])(arrayPtr);
}

///
@system pure nothrow
unittest
{
int[] a = [1, 2];
auto app2 = appender(&a);
assert(app2.data == [1, 2]);
assert(a == [1, 2]);
app2 ~= 3;
app2 ~= [4, 5, 6];
assert(app2.data == [1, 2, 3, 4, 5, 6]);
assert(a == [1, 2, 3, 4, 5, 6]);

app2.reserve(5);
assert(app2.capacity >= 5);
}

@system unittest
{
import std.exception;
Expand Down
23 changes: 23 additions & 0 deletions std/ascii.d
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,29 @@ enum LetterCase : bool
lower /// Lower case letters
}

///
@safe unittest
{
import std.conv : to;

assert(42.to!string(16, LetterCase.upper) == "2A");
assert(42.to!string(16, LetterCase.lower) == "2a");
}

///
@system unittest
{
import std.digest.hmac : hmac;
import std.digest.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");
}

/// Newline sequence for this system.
version(Windows)
immutable newline = "\r\n";
Expand Down
22 changes: 22 additions & 0 deletions std/base64.d
Original file line number Diff line number Diff line change
Expand Up @@ -1721,6 +1721,21 @@ template Base64Impl(char Map62th, char Map63th, char Padding = '=')
}
}

///
@safe unittest
{
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");
}

/**
* Exception thrown upon encountering Base64 encoding or decoding errors.
Expand All @@ -1734,6 +1749,13 @@ class Base64Exception : Exception
}
}

///
@system unittest
{
import std.exception : assertThrown;
assertThrown!Base64Exception(Base64.decode("ab|c"));
}


@system unittest
{
Expand Down