06e8ee96a5
- Add TokenClaims message for JWT payload structure with user id, issuer, timestamps, and scopes - Implement IssueTokenRequest/Response for creating access and refresh tokens with TTL support - Create RefreshTokenRequest/Response for token rotation functionality - Define RevokeTokenRequest/Response with support for single token or user-wide revocation - Add VerifyTokenRequest/Response for validating JWT tokens with detailed claims information - Implement signing key distribution system with GetSigningKeysRequest/Response - Create TokenService gRPC service with IssueToken, RefreshToken, RevokeToken, VerifyToken, and GetSigningKeys methods - Add build.rs configuration to compile proto files using tonic_prost_build - Include channel, channel_settings, member, and permission protocol definitions for IM services - Generate Rust code bindings through pb/core.rs and pb/im.rs modules
204 lines
6.0 KiB
Rust
204 lines
6.0 KiB
Rust
use imks::socket::packet::{Packet, PacketType};
|
|
use imks::socket::parser;
|
|
use serde_json::json;
|
|
|
|
#[test]
|
|
fn test_socket_io_connect_encoding() {
|
|
let packet = Packet::connect("/", None);
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "0");
|
|
|
|
let packet = Packet::connect("/admin", Some(json!({"sid": "abc123"})));
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "0/admin,{\"sid\":\"abc123\"}");
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_disconnect_encoding() {
|
|
let packet = Packet::disconnect("/");
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "1");
|
|
|
|
let packet = Packet::disconnect("/admin");
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "1/admin,");
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_event_encoding() {
|
|
let packet = Packet::event("/", json!(["foo"]), None);
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "2[\"foo\"]");
|
|
|
|
let packet = Packet::event("/admin", json!(["bar"]), None);
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "2/admin,[\"bar\"]");
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_event_with_ack_encoding() {
|
|
let packet = Packet::event("/", json!(["foo"]), Some(12));
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "212[\"foo\"]");
|
|
|
|
let packet = Packet::event("/admin", json!(["bar"]), Some(13));
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "2/admin,13[\"bar\"]");
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_ack_encoding() {
|
|
let packet = Packet::ack("/", json!([]), 12);
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "312[]");
|
|
|
|
let packet = Packet::ack("/admin", json!(["bar"]), 13);
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "3/admin,13[\"bar\"]");
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_connect_error_encoding() {
|
|
let packet = Packet::connect_error("/", "Not authorized");
|
|
let encoded = parser::encode(&packet);
|
|
assert_eq!(encoded, "4{\"message\":\"Not authorized\"}");
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_connect_decoding() {
|
|
let packet = parser::decode("0").unwrap();
|
|
assert_eq!(packet.packet_type, PacketType::Connect);
|
|
assert_eq!(packet.namespace, "/");
|
|
assert!(packet.data.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_connect_with_namespace_decoding() {
|
|
let packet = parser::decode("0/admin,{\"sid\":\"abc\"}").unwrap();
|
|
assert_eq!(packet.packet_type, PacketType::Connect);
|
|
assert_eq!(packet.namespace, "/admin");
|
|
assert!(packet.data.is_some());
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_disconnect_decoding() {
|
|
let packet = parser::decode("1").unwrap();
|
|
assert_eq!(packet.packet_type, PacketType::Disconnect);
|
|
assert_eq!(packet.namespace, "/");
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_disconnect_with_namespace_decoding() {
|
|
let packet = parser::decode("1/admin,").unwrap();
|
|
assert_eq!(packet.packet_type, PacketType::Disconnect);
|
|
assert_eq!(packet.namespace, "/admin");
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_event_decoding() {
|
|
let packet = parser::decode("2[\"foo\"]").unwrap();
|
|
assert_eq!(packet.packet_type, PacketType::Event);
|
|
assert_eq!(packet.namespace, "/");
|
|
assert_eq!(packet.data, Some(json!(["foo"])));
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_event_with_namespace_decoding() {
|
|
let packet = parser::decode("2/admin,[\"bar\"]").unwrap();
|
|
assert_eq!(packet.packet_type, PacketType::Event);
|
|
assert_eq!(packet.namespace, "/admin");
|
|
assert_eq!(packet.data, Some(json!(["bar"])));
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_event_with_ack_decoding() {
|
|
let packet = parser::decode("212[\"foo\"]").unwrap();
|
|
assert_eq!(packet.packet_type, PacketType::Event);
|
|
assert_eq!(packet.id, Some(12));
|
|
assert_eq!(packet.data, Some(json!(["foo"])));
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_ack_decoding() {
|
|
let packet = parser::decode("312[]").unwrap();
|
|
assert_eq!(packet.packet_type, PacketType::Ack);
|
|
assert_eq!(packet.id, Some(12));
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_connect_error_decoding() {
|
|
let packet = parser::decode("4{\"message\":\"Not authorized\"}").unwrap();
|
|
assert_eq!(packet.packet_type, PacketType::ConnectError);
|
|
assert_eq!(packet.data, Some(json!({"message": "Not authorized"})));
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_binary_event_encoding() {
|
|
let packet = Packet::binary_event(
|
|
"/",
|
|
json!(["baz", {"_placeholder": true, "num": 0}]),
|
|
None,
|
|
vec![vec![0x01, 0x02, 0x03, 0x04]],
|
|
);
|
|
let encoded = parser::encode(&packet);
|
|
assert!(encoded.starts_with("51-"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_binary_ack_encoding() {
|
|
let packet = Packet::binary_ack(
|
|
"/",
|
|
json!(["bar", {"_placeholder": true, "num": 0}]),
|
|
15,
|
|
vec![vec![0x01, 0x02, 0x03, 0x04]],
|
|
);
|
|
let encoded = parser::encode(&packet);
|
|
assert!(encoded.starts_with("61-"));
|
|
assert!(encoded.contains("15"));
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_roundtrip() {
|
|
let original = Packet::event("/admin", json!(["hello", "world"]), Some(42));
|
|
let encoded = parser::encode(&original);
|
|
let decoded = parser::decode(&encoded).unwrap();
|
|
|
|
assert_eq!(decoded.packet_type, original.packet_type);
|
|
assert_eq!(decoded.namespace, original.namespace);
|
|
assert_eq!(decoded.id, original.id);
|
|
assert_eq!(decoded.data, original.data);
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_namespace_handling() {
|
|
let namespaces = vec!["/", "/admin", "/chat", "/api/v1"];
|
|
|
|
for ns in namespaces {
|
|
let packet = Packet::event(ns, json!(["test"]), None);
|
|
let encoded = parser::encode(&packet);
|
|
let decoded = parser::decode(&encoded).unwrap();
|
|
assert_eq!(decoded.namespace, ns);
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_socket_io_complex_data() {
|
|
let complex_data = json!([
|
|
"event_name",
|
|
{
|
|
"user": {
|
|
"id": 123,
|
|
"name": "test",
|
|
"roles": ["admin", "user"]
|
|
},
|
|
"timestamp": 1234567890
|
|
}
|
|
]);
|
|
|
|
let packet = Packet::event("/", complex_data.clone(), None);
|
|
let encoded = parser::encode(&packet);
|
|
let decoded = parser::decode(&encoded).unwrap();
|
|
|
|
assert_eq!(decoded.data, Some(complex_data));
|
|
}
|