Compare commits

...

4 Commits

Author SHA1 Message Date
Tristan B. Velloza Kildaire b465585e91 Client (unittest)
- Added try-and-catch

Client

- Fixed error handling in `joinChannel(string)`
2023-11-18 11:42:35 +02:00
Tristan B. Velloza Kildaire 4ad56763d8 Client
- Added `joinChannel_imp(string channelName)` which performs the joining of a channel and returns a `Future`
- Added `joinChannel(string channelName)` which is a neat wrapper around the above
- `enumerateChannels(ulong offset, ubyte limit)` now handles incorrect replies by throwing a `ProtocolException` on wrong reply type

Client (unittests)

- Added a unit test for `joinChannel(string channelName)`
2023-11-18 11:13:20 +02:00
Tristan B. Velloza Kildaire 455bd6fa06 Tings
- Added some testing mixin template
2023-11-18 11:11:54 +02:00
Tristan B. Velloza Kildaire 0d5b7c42e4 Exceptions
- Added `DanteException`
- Added `ProtocolException`
- Added `CommandException`
2023-11-18 11:11:37 +02:00
3 changed files with 157 additions and 0 deletions

View File

@ -8,6 +8,7 @@ import davinci;
import tristanable;
import guillotine;
import guillotine.providers.sequential;
import dante.exceptions;
version(dbg)
{
@ -134,12 +135,73 @@ public class DanteClient
return makeRequest(msg);
}
public Future joinChannel_imp(string channelName)
{
import davinci.c2s.channels : ChannelMembership;
import davinci;
ChannelMembership chanMembershipReq = new ChannelMembership();
chanMembershipReq.join(channelName);
BaseMessage msg = new BaseMessage(MessageType.CLIENT_TO_SERVER, CommandType.MEMBERSHIP_JOIN, chanMembershipReq);
return makeRequest(msg);
}
public void joinChannel(string channelName)
{
import davinci.c2s.channels : ChannelMembership;
import davinci;
BaseMessage response = cast(BaseMessage)joinChannel_imp(channelName).await().getValue().value.object;
import std.stdio;
writeln("Hallo");
writeln("Hallo");
writeln("Hallo");
writeln("Hallo");
writeln("Hallo");
writeln("Hallo");
writeln("Hallo");
writeln("Hallo");
writeln("Hallo");
// TODO: For absolute sanity we should check that
// ... it actually decoded to the type we EXPECT
// ... to be here (this would safeguard against
// ... bad server implementations)
// TODO: Make teh below a `mixin template`
Command responseCommand = response.getCommand();
ChannelMembership chanMemResp = cast(ChannelMembership)responseCommand;
if(chanMemResp is null)
{
throw ProtocolException.expectedMessageKind(ChannelMembership.classinfo, responseCommand);
}
if(chanMemResp.wasGood())
{
return;
}
else
{
throw new CommandException("Could not join channel '"~channelName~"'");
}
}
public string[] enumerateChannels(ulong offset, ubyte limit)
{
import davinci.c2s.channels : ChannelEnumerateReply;
BaseMessage response = cast(BaseMessage)enumerateChannels_imp(offset, limit).await().getValue().value.object;
// TODO: For absolute sanity we should check that
// ... it actually decoded to the type we EXPECT
// ... to be here (this would safeguard against
// ... bad server implementations)
// TODO: Make teh below a `mixin template`
ChannelEnumerateReply responseCommand = cast(ChannelEnumerateReply)response.getCommand();
if(responseCommand is null)
{
throw ProtocolException.expectedMessageKind(ChannelEnumerateReply.classinfo, responseCommand);
}
return responseCommand.getChannels();
}
@ -263,5 +325,30 @@ unittest
string[] channels = client.enumerateChannels();
writeln(dumpArray!(channels));
client.stop();
}
unittest
{
DanteClient client = new DanteClient(new UnixAddress("/tmp/renaissance.sock"));
client.start();
try
{
writeln("Joining channel #general...");
client.joinChannel("#general");
writeln("Joined");
}
catch(DanteException e)
{
writeln("Got exception: ", e);
}
// string[] members = client.getMembers("#general");
// client.leaveChannel("#general");
client.stop();
}

43
source/dante/exceptions.d Normal file
View File

@ -0,0 +1,43 @@
module dante.exceptions;
public abstract class DanteException : Exception
{
this(string msg)
{
super(msg);
}
}
public class CommandException : DanteException
{
this(string msg)
{
super(msg);
}
}
import std.conv : to;
public class ProtocolException : DanteException
{
this(string msg)
{
super(msg);
}
public static ProtocolException expectedMessageKind(TypeInfo_Class expected, Object got)
{
string message = "Expected message of type '"~to!(string)(expected);
if(got is null)
{
message ~= " but got null";
}
else
{
message ~= " but got a message of type '"~to!(string)(got.classinfo)~"'";
}
return new ProtocolException(message);
}
}

27
source/dante/tings.d Normal file
View File

@ -0,0 +1,27 @@
module dante.tings;
import dante;
import dante.exceptions : ProtocolException;
import davinci.base : Command;
public mixin template Expect_n_handle(ExpectedType, alias command)
if(__traits(isSame, typeof(command), Command))
{
/**
* Check that we can cast to `ExpectedType`
*
* If not, we throw anexception
*/
ExpectedType expectedMessage = cast(ExpectedType)command;
void Expect_n_handle()
{
import std.stdio : writeln;
writeln("Hello testing");
if(expectedMessage is null)
{
throw ProtocolException.expectedMessageKind(expectedMessage.classinfo, command);
}
}
}