Merge branch 'master' of github.com:vibe-d/vibe-core
This commit is contained in:
commit
531398e28d
|
@ -464,6 +464,7 @@ struct FileStream {
|
||||||
cb => eventDriver.files.read(m_fd, ctx.ptr, dst, mode, cb),
|
cb => eventDriver.files.read(m_fd, ctx.ptr, dst, mode, cb),
|
||||||
cb => eventDriver.files.cancelRead(m_fd)
|
cb => eventDriver.files.cancelRead(m_fd)
|
||||||
);
|
);
|
||||||
|
ctx.ptr += res[2];
|
||||||
enforce(res[1] == IOStatus.ok, "Failed to read data from disk.");
|
enforce(res[1] == IOStatus.ok, "Failed to read data from disk.");
|
||||||
return res[2];
|
return res[2];
|
||||||
}
|
}
|
||||||
|
|
27
tests/args.d
Normal file
27
tests/args.d
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
/+ dub.json:
|
||||||
|
{
|
||||||
|
"name": "tests",
|
||||||
|
"description": "Command-line argument test",
|
||||||
|
"dependencies": {
|
||||||
|
"vibe-core": {"path": "../"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+/
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import vibe.core.args;
|
||||||
|
import vibe.core.log;
|
||||||
|
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
shared static this()
|
||||||
|
{
|
||||||
|
string argtest;
|
||||||
|
readOption("argtest", &argtest, "Test argument");
|
||||||
|
writeln("argtest=", argtest);
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
finalizeCommandLineOptions();
|
||||||
|
}
|
10
tests/args.sh
Executable file
10
tests/args.sh
Executable file
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
die() { echo "$@" 1>&2 ; exit 1; }
|
||||||
|
|
||||||
|
( dub args.d | grep -q '^argtest=$' ) || die "Fail (no argument)"
|
||||||
|
( dub args.d --argtest=aoeu | grep -q '^argtest=aoeu$' ) || die "Fail (with argument)"
|
||||||
|
( ( ! dub args.d --inexisting 2>&1 ) | grep -qF 'Unrecognized command line option' ) || die "Fail (unknown argument)"
|
||||||
|
|
||||||
|
echo 'OK'
|
107
tests/dirwatcher.d
Normal file
107
tests/dirwatcher.d
Normal file
|
@ -0,0 +1,107 @@
|
||||||
|
/+ dub.json:
|
||||||
|
{
|
||||||
|
"name": "tests",
|
||||||
|
"description": "Test for vibe.d's DirectoryWatcher.",
|
||||||
|
"dependencies": {
|
||||||
|
"vibe-core": {"path": "../"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+/
|
||||||
|
import vibe.core.core;
|
||||||
|
import vibe.core.file;
|
||||||
|
import vibe.core.log;
|
||||||
|
import vibe.core.path;
|
||||||
|
import std.algorithm : canFind, all;
|
||||||
|
import std.file, std.process;
|
||||||
|
import std.format : format;
|
||||||
|
import std.conv : to;
|
||||||
|
import std.path : buildPath;
|
||||||
|
import std.typecons : No, Yes;
|
||||||
|
import core.exception : AssertError;
|
||||||
|
import core.time : msecs, seconds;
|
||||||
|
|
||||||
|
void runTest()
|
||||||
|
{
|
||||||
|
auto dir = buildPath(tempDir, format("dirwatcher_test_%d", thisProcessID()));
|
||||||
|
mkdir(dir);
|
||||||
|
scope(exit) rmdirRecurse(dir);
|
||||||
|
|
||||||
|
DirectoryWatcher watcher;
|
||||||
|
try watcher = Path(dir).watchDirectory(No.recursive);
|
||||||
|
catch (AssertError e) {
|
||||||
|
logInfo("DirectoryWatcher not yet implemented. Skipping test.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
DirectoryChange[] changes;
|
||||||
|
assert(!watcher.readChanges(changes, 500.msecs));
|
||||||
|
|
||||||
|
auto foo = dir.buildPath("foo");
|
||||||
|
|
||||||
|
alias Type = DirectoryChangeType;
|
||||||
|
static DirectoryChange dc(Type t, string p) { return DirectoryChange(t, Path(p)); }
|
||||||
|
void check(DirectoryChange[] expected)
|
||||||
|
{
|
||||||
|
sleep(100.msecs);
|
||||||
|
assert(watcher.readChanges(changes, 100.msecs), "Could not read changes for " ~ expected.to!string);
|
||||||
|
assert(expected.all!((a)=> changes.canFind(a))(), "Change is not what was expected, got: " ~ changes.to!string ~ " but expected: " ~ expected.to!string);
|
||||||
|
assert(!watcher.readChanges(changes, 0.msecs), "Changes were returned when they shouldn't have, for " ~ expected.to!string);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(foo, null);
|
||||||
|
check([dc(Type.added, foo)]);
|
||||||
|
sleep(1.seconds); // OSX has a second resolution on file modification times
|
||||||
|
write(foo, [0, 1]);
|
||||||
|
check([dc(Type.modified, foo)]);
|
||||||
|
remove(foo);
|
||||||
|
check([dc(Type.removed, foo)]);
|
||||||
|
write(foo, null);
|
||||||
|
sleep(1.seconds);
|
||||||
|
write(foo, [0, 1]);
|
||||||
|
sleep(100.msecs);
|
||||||
|
remove(foo);
|
||||||
|
check([dc(Type.added, foo), dc(Type.modified, foo), dc(Type.removed, foo)]);
|
||||||
|
|
||||||
|
auto subdir = dir.buildPath("subdir");
|
||||||
|
mkdir(subdir);
|
||||||
|
check([dc(Type.added, subdir)]);
|
||||||
|
auto bar = subdir.buildPath("bar");
|
||||||
|
write(bar, null);
|
||||||
|
assert(!watcher.readChanges(changes, 100.msecs));
|
||||||
|
remove(bar);
|
||||||
|
watcher = Path(dir).watchDirectory(Yes.recursive);
|
||||||
|
write(foo, null);
|
||||||
|
sleep(1.seconds);
|
||||||
|
write(foo, [0, 1]);
|
||||||
|
sleep(100.msecs);
|
||||||
|
remove(foo);
|
||||||
|
|
||||||
|
write(bar, null);
|
||||||
|
sleep(1.seconds);
|
||||||
|
write(bar, [0, 1]);
|
||||||
|
sleep(100.msecs);
|
||||||
|
remove(bar);
|
||||||
|
check([dc(Type.added, foo), dc(Type.modified, foo), dc(Type.removed, foo),
|
||||||
|
dc(Type.added, bar), dc(Type.modified, bar), dc(Type.removed, bar)]);
|
||||||
|
|
||||||
|
write(foo, null);
|
||||||
|
sleep(100.msecs);
|
||||||
|
rename(foo, bar);
|
||||||
|
sleep(100.msecs);
|
||||||
|
remove(bar);
|
||||||
|
check([dc(Type.added, foo), dc(Type.removed, foo), dc(Type.added, bar), dc(Type.removed, bar)]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
runTask({
|
||||||
|
try runTest();
|
||||||
|
catch (Throwable th) {
|
||||||
|
logError("Test failed: %s", th.toString());
|
||||||
|
ret = 1;
|
||||||
|
} finally exitEventLoop(true);
|
||||||
|
});
|
||||||
|
runEventLoop();
|
||||||
|
return ret;
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
/++ dub.sdl:
|
/+ dub.sdl:
|
||||||
name "test"
|
name "test"
|
||||||
description "Tests vibe.d's std.concurrency integration"
|
description "Tests vibe.d's std.concurrency integration"
|
||||||
dependency "vibe-core" path="../"
|
dependency "vibe-core" path="../"
|
||||||
|
|
58
tests/vibe.core.concurrency.1408.d
Normal file
58
tests/vibe.core.concurrency.1408.d
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
/+ dub.sdl:
|
||||||
|
name "tests"
|
||||||
|
description "std.concurrency integration issue"
|
||||||
|
dependency "vibe-core" path="../"
|
||||||
|
versions "VibeDefaultMain"
|
||||||
|
+/
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import vibe.core.concurrency;
|
||||||
|
import vibe.core.core;
|
||||||
|
import vibe.core.log;
|
||||||
|
import core.time : msecs;
|
||||||
|
import std.functional : toDelegate;
|
||||||
|
|
||||||
|
void test()
|
||||||
|
{
|
||||||
|
auto t = runTask({
|
||||||
|
bool gotit;
|
||||||
|
receive((int i) { assert(i == 10); gotit = true; });
|
||||||
|
assert(gotit);
|
||||||
|
sleep(10.msecs);
|
||||||
|
});
|
||||||
|
|
||||||
|
t.tid.send(10);
|
||||||
|
t.tid.send(11); // never received
|
||||||
|
t.join();
|
||||||
|
|
||||||
|
// ensure that recycled fibers will get a clean message queue
|
||||||
|
auto t2 = runTask({
|
||||||
|
bool gotit;
|
||||||
|
receive((int i) { assert(i == 12); gotit = true; });
|
||||||
|
assert(gotit);
|
||||||
|
});
|
||||||
|
t2.tid.send(12);
|
||||||
|
t2.join();
|
||||||
|
|
||||||
|
// test worker tasks
|
||||||
|
auto t3 = runWorkerTaskH({
|
||||||
|
bool gotit;
|
||||||
|
receive((int i) { assert(i == 13); gotit = true; });
|
||||||
|
assert(gotit);
|
||||||
|
});
|
||||||
|
|
||||||
|
t3.tid.send(13);
|
||||||
|
sleep(10.msecs);
|
||||||
|
|
||||||
|
logInfo("Success.");
|
||||||
|
|
||||||
|
exitEventLoop(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
shared static this()
|
||||||
|
{
|
||||||
|
setLogFormat(FileLogger.Format.threadTime, FileLogger.Format.threadTime);
|
||||||
|
runTask(toDelegate(&test));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
59
tests/vibe.core.core.1590.d
Normal file
59
tests/vibe.core.core.1590.d
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
/+ dub.sdl:
|
||||||
|
name "tests"
|
||||||
|
description "Semaphore hang"
|
||||||
|
dependency "vibe-core" path="../"
|
||||||
|
+/
|
||||||
|
module test;
|
||||||
|
import std.stdio;
|
||||||
|
import std.socket;
|
||||||
|
import std.datetime;
|
||||||
|
import std.functional;
|
||||||
|
import core.time;
|
||||||
|
import vibe.core.core;
|
||||||
|
import vibe.core.log;
|
||||||
|
import vibe.core.concurrency;
|
||||||
|
import vibe.core.connectionpool;
|
||||||
|
|
||||||
|
class Conn {}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
runTask({
|
||||||
|
// create pool with 2 max connections
|
||||||
|
bool[int] results;
|
||||||
|
auto pool = new ConnectionPool!Conn({ return new Conn; }, 2);
|
||||||
|
auto task = Task.getThis(); // main task
|
||||||
|
void worker(int id) {
|
||||||
|
{
|
||||||
|
auto conn = pool.lockConnection(); // <-- worker(4) hangs here
|
||||||
|
sleep(1.msecs); // <-- important, without sleep everything works fine
|
||||||
|
}
|
||||||
|
task.send(id); // send signal to the main task
|
||||||
|
}
|
||||||
|
// run 4 tasks (2 * pool max connections)
|
||||||
|
runTask(&worker, 1);
|
||||||
|
runTask(&worker, 2);
|
||||||
|
runTask(&worker, 3);
|
||||||
|
runTask(&worker, 4);
|
||||||
|
|
||||||
|
// wait for first signal and run one more task
|
||||||
|
results[receiveOnly!int] = true;
|
||||||
|
runTask(&worker, 5);
|
||||||
|
|
||||||
|
// wait for other signals
|
||||||
|
results[receiveOnly!int] = true;
|
||||||
|
results[receiveOnly!int] = true;
|
||||||
|
results[receiveOnly!int] = true;
|
||||||
|
results[receiveOnly!int] = true;
|
||||||
|
|
||||||
|
foreach (r; results.byKey)
|
||||||
|
assert(r >= 1 && r <= 5);
|
||||||
|
|
||||||
|
exitEventLoop();
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimer(1.seconds, { assert(false, "Test has hung."); });
|
||||||
|
|
||||||
|
runEventLoop();
|
||||||
|
}
|
||||||
|
|
51
tests/vibe.core.core.refcount.d
Normal file
51
tests/vibe.core.core.refcount.d
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
/+ dub.sdl:
|
||||||
|
name "tests"
|
||||||
|
description "Invalid ref count after runTask"
|
||||||
|
dependency "vibe-core" path="../"
|
||||||
|
+/
|
||||||
|
module test;
|
||||||
|
import vibe.core.core;
|
||||||
|
import std.stdio;
|
||||||
|
|
||||||
|
struct RC {
|
||||||
|
int* rc;
|
||||||
|
this(int* rc) { this.rc = rc; }
|
||||||
|
this(this) {
|
||||||
|
if (rc) {
|
||||||
|
(*rc)++;
|
||||||
|
writefln("addref %s", *rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
~this() {
|
||||||
|
if (rc) {
|
||||||
|
(*rc)--;
|
||||||
|
writefln("release %s", *rc);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
int rc = 1;
|
||||||
|
bool done = false;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto s = RC(&rc);
|
||||||
|
assert(rc == 1);
|
||||||
|
runTask((RC st) {
|
||||||
|
assert(rc == 2);
|
||||||
|
st = RC.init;
|
||||||
|
assert(rc == 1);
|
||||||
|
exitEventLoop();
|
||||||
|
done = true;
|
||||||
|
}, s);
|
||||||
|
assert(rc == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(rc == 1);
|
||||||
|
|
||||||
|
runEventLoop();
|
||||||
|
|
||||||
|
assert(rc == 0);
|
||||||
|
assert(done);
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
/++ dub.sdl:
|
/+ dub.sdl:
|
||||||
name "test"
|
name "test"
|
||||||
dependency "vibe-core" path=".."
|
dependency "vibe-core" path=".."
|
||||||
+/
|
+/
|
||||||
|
@ -12,16 +12,23 @@ void main()
|
||||||
{
|
{
|
||||||
auto f = openFile("test.dat", FileMode.createTrunc);
|
auto f = openFile("test.dat", FileMode.createTrunc);
|
||||||
assert(f.size == 0);
|
assert(f.size == 0);
|
||||||
|
assert(f.tell == 0);
|
||||||
f.write(bytes!(1, 2, 3, 4, 5));
|
f.write(bytes!(1, 2, 3, 4, 5));
|
||||||
assert(f.size == 5);
|
assert(f.size == 5);
|
||||||
|
assert(f.tell == 5);
|
||||||
f.seek(0);
|
f.seek(0);
|
||||||
|
assert(f.tell == 0);
|
||||||
f.write(bytes!(1, 2, 3, 4, 5));
|
f.write(bytes!(1, 2, 3, 4, 5));
|
||||||
assert(f.size == 5);
|
assert(f.size == 5);
|
||||||
|
assert(f.tell == 5);
|
||||||
f.write(bytes!(6, 7, 8, 9, 10));
|
f.write(bytes!(6, 7, 8, 9, 10));
|
||||||
assert(f.size == 10);
|
assert(f.size == 10);
|
||||||
|
assert(f.tell == 10);
|
||||||
ubyte[5] dst;
|
ubyte[5] dst;
|
||||||
f.seek(2);
|
f.seek(2);
|
||||||
|
assert(f.tell == 2);
|
||||||
f.read(dst);
|
f.read(dst);
|
||||||
|
assert(f.tell == 7);
|
||||||
assert(dst[] == bytes!(3, 4, 5, 6, 7));
|
assert(dst[] == bytes!(3, 4, 5, 6, 7));
|
||||||
f.close();
|
f.close();
|
||||||
|
|
||||||
|
|
42
tests/vibe.core.net.1376.d
Normal file
42
tests/vibe.core.net.1376.d
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/+ dub.sdl:
|
||||||
|
name "tests"
|
||||||
|
description "TCP disconnect task issue"
|
||||||
|
dependency "vibe-core" path="../"
|
||||||
|
versions "VibeDefaultMain"
|
||||||
|
+/
|
||||||
|
module test;
|
||||||
|
|
||||||
|
import vibe.core.core;
|
||||||
|
import vibe.core.net;
|
||||||
|
import core.time : msecs;
|
||||||
|
|
||||||
|
shared static this()
|
||||||
|
{
|
||||||
|
listenTCP(11375,(conn){
|
||||||
|
auto td = runTask!TCPConnection((conn) {
|
||||||
|
ubyte [3] buf;
|
||||||
|
try {
|
||||||
|
conn.read(buf);
|
||||||
|
assert(false, "Expected read() to throw an exception.");
|
||||||
|
} catch (Exception) {} // expected
|
||||||
|
}, conn);
|
||||||
|
sleep(10.msecs);
|
||||||
|
conn.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
runTask({
|
||||||
|
try {
|
||||||
|
auto conn = connectTCP("127.0.0.1", 11375);
|
||||||
|
conn.write("a");
|
||||||
|
conn.close();
|
||||||
|
} catch (Exception e) assert(false, e.msg);
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto conn = connectTCP("127.0.0.1", 11375);
|
||||||
|
conn.close();
|
||||||
|
} catch (Exception e) assert(false, e.msg);
|
||||||
|
|
||||||
|
sleep(50.msecs);
|
||||||
|
exitEventLoop();
|
||||||
|
});
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
/++ dub.sdl:
|
/+ dub.sdl:
|
||||||
name "test"
|
name "test"
|
||||||
description "TCP disconnect task issue"
|
description "TCP disconnect task issue"
|
||||||
dependency "vibe-core" path="../"
|
dependency "vibe-core" path="../"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
/++ dub.sdl:
|
/+ dub.sdl:
|
||||||
name "test"
|
name "test"
|
||||||
description "TCP disconnect task issue"
|
description "TCP disconnect task issue"
|
||||||
dependency "vibe-core" path="../"
|
dependency "vibe-core" path="../"
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
/++ dub.sdl:
|
/+ dub.sdl:
|
||||||
name "test"
|
name "test"
|
||||||
description "Invalid memory operation on TCP connection leakage at shutdown"
|
description "Invalid memory operation on TCP connection leakage at shutdown"
|
||||||
dependency "vibe-core" path="../"
|
dependency "vibe-core" path="../"
|
||||||
|
debugVersions "VibeAsyncLog"
|
||||||
+/
|
+/
|
||||||
module test;
|
module test;
|
||||||
|
|
||||||
|
|
10
travis-ci.sh
10
travis-ci.sh
|
@ -21,7 +21,13 @@ if [ ${BUILD_EXAMPLE=1} -eq 1 ]; then
|
||||||
fi
|
fi
|
||||||
if [ ${RUN_TEST=1} -eq 1 ]; then
|
if [ ${RUN_TEST=1} -eq 1 ]; then
|
||||||
for ex in `\ls -1 tests/*.d`; do
|
for ex in `\ls -1 tests/*.d`; do
|
||||||
echo "[INFO] Running test $ex"
|
script="${ex:0:-2}.sh"
|
||||||
dub --temp-build --compiler=$DC --single $ex # --override-config vibe-core/$CONFIG
|
if [ -e "$script" ]; then
|
||||||
|
echo "[INFO] Running test scipt $script"
|
||||||
|
(cd tests && "./${script:6}")
|
||||||
|
else
|
||||||
|
echo "[INFO] Running test $ex"
|
||||||
|
dub --temp-build --compiler=$DC --single $ex # --override-config vibe-core/$CONFIG
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
Loading…
Reference in a new issue