blob: e9563025cd28e2ee77231c8cd2a085f9ae224a6d [file]
// // Licensed to the Apache Software Foundation (ASF) under one
// // or more contributor license agreements. See the NOTICE file
// // distributed with this work for additional information
// // regarding copyright ownership. The ASF licenses this file
// // to you under the Apache License, Version 2.0 (the
// // "License"); you may not use this file except in compliance
// // with the License. You may obtain a copy of the License at
// //
// // http://www.apache.org/licenses/LICENSE-2.0
// //
// // Unless required by applicable law or agreed to in writing,
// // software distributed under the License is distributed on an
// // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// // KIND, either express or implied. See the License for the
// // specific language governing permissions and limitations
// // under the License.
using Apache.Iggy.Contracts;
using Apache.Iggy.Enums;
using Apache.Iggy.Exceptions;
using Apache.Iggy.Kinds;
using Apache.Iggy.Messages;
using Apache.Iggy.Tests.Integrations.Attributes;
using Apache.Iggy.Tests.Integrations.Fixtures;
using Shouldly;
using Partitioning = Apache.Iggy.Kinds.Partitioning;
namespace Apache.Iggy.Tests.Integrations;
public class SystemTests
{
[ClassDataSource<IggyServerFixture>(Shared = SharedType.PerAssembly)]
public required IggyServerFixture Fixture { get; init; }
[Test]
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
public async Task GetClients_Should_Return_NonEmptyClientsList(Protocol protocol)
{
var client = await Fixture.CreateAuthenticatedClient(protocol);
IReadOnlyList<ClientResponse> clients = await client.GetClientsAsync();
clients.ShouldNotBeNull();
clients.Count.ShouldBeGreaterThanOrEqualTo(1);
foreach (var c in clients)
{
c.ClientId.ShouldNotBe(0u);
c.Address.ShouldNotBeNullOrEmpty();
c.Transport.ShouldBe(Protocol.Tcp);
}
}
[Test]
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
public async Task GetClient_Should_Return_CorrectClient(Protocol protocol)
{
var client = await Fixture.CreateAuthenticatedClient(protocol);
var tcpClient = await Fixture.CreateClient(Protocol.Tcp);
await tcpClient.LoginUser("iggy", "iggy");
var clientInfo = await tcpClient.GetMeAsync();
clientInfo.ShouldNotBeNull();
var response = await client.GetClientByIdAsync(clientInfo.ClientId);
response.ShouldNotBeNull();
response.ClientId.ShouldBe(clientInfo.ClientId);
response.UserId.ShouldNotBeNull();
response.UserId.Value.ShouldBeGreaterThanOrEqualTo(0u);
response.Address.ShouldNotBeNullOrEmpty();
response.Transport.ShouldBe(Protocol.Tcp);
response.ConsumerGroupsCount.ShouldBe(0);
response.ConsumerGroups.ShouldBeEmpty();
}
[Test]
[SkipHttp]
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
public async Task GetMe_Tcp_Should_Return_MyClient(Protocol protocol)
{
var client = await Fixture.CreateTcpClient();
var me = await client.GetMeAsync();
me.ShouldNotBeNull();
me.ClientId.ShouldNotBe(0u);
me.UserId.ShouldBe(0u);
me.Address.ShouldNotBeNullOrEmpty();
me.Transport.ShouldBe(Protocol.Tcp);
}
[Test]
[SkipTcp]
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
public async Task GetMe_HTTP_Should_Throw_FeatureUnavailableException(Protocol protocol)
{
var client = await Fixture.CreateHttpClient();
await Should.ThrowAsync<FeatureUnavailableException>(() => client.GetMeAsync());
}
[Test]
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
public async Task GetClient_WithConsumerGroup_Should_Return_CorrectClient(Protocol protocol)
{
var client = await Fixture.CreateAuthenticatedClient(protocol);
var streamName = $"sys-cg-{Guid.NewGuid():N}";
var tcpClient = await Fixture.CreateClient(Protocol.Tcp);
await tcpClient.LoginUser("iggy", "iggy");
var stream = await tcpClient.CreateStreamAsync(streamName);
await tcpClient.CreateTopicAsync(Identifier.String(streamName), "first_topic", 2);
var secondTopic = await tcpClient.CreateTopicAsync(Identifier.String(streamName), "second_topic", 2);
var consumerGroup = await tcpClient.CreateConsumerGroupAsync(
Identifier.String(streamName), Identifier.String("second_topic"), "test_consumer_group");
await tcpClient.JoinConsumerGroupAsync(Identifier.String(streamName),
Identifier.String("second_topic"), Identifier.String("test_consumer_group"));
var me = await tcpClient.GetMeAsync();
var response = await client.GetClientByIdAsync(me!.ClientId);
response.ShouldNotBeNull();
response.Address.ShouldNotBeNullOrEmpty();
response.Transport.ShouldBe(Protocol.Tcp);
response.ConsumerGroupsCount.ShouldBe(1);
response.ConsumerGroups.ShouldNotBeEmpty();
response.ConsumerGroups.ShouldContain(x => x.GroupId == consumerGroup!.Id);
response.ConsumerGroups.ShouldContain(x => x.StreamId == stream!.Id);
response.ConsumerGroups.ShouldContain(x => x.TopicId == (int)secondTopic!.Id);
}
[Test]
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
public async Task GetStats_Should_ReturnValidResponse(Protocol protocol)
{
var client = await Fixture.CreateAuthenticatedClient(protocol);
// Create a stream/topic and send a message so stats are non-zero
var streamName = $"sys-stats-{Guid.NewGuid():N}";
await client.CreateStreamAsync(streamName);
await client.CreateTopicAsync(Identifier.String(streamName), "stats-topic", 1);
await client.SendMessagesAsync(Identifier.String(streamName),
Identifier.String("stats-topic"), Partitioning.None(),
[new Message(Guid.NewGuid(), "Test message"u8.ToArray())]);
var response = await client.GetStatsAsync();
response.ShouldNotBeNull();
response.ProcessId.ShouldBeGreaterThanOrEqualTo(0);
response.CpuUsage.ShouldBeGreaterThanOrEqualTo(0);
response.TotalCpuUsage.ShouldBeGreaterThanOrEqualTo(0);
response.MemoryUsage.ShouldBeGreaterThanOrEqualTo(0u);
response.TotalMemory.ShouldBeGreaterThanOrEqualTo(0u);
response.AvailableMemory.ShouldNotBe(0u);
response.RunTime.ShouldBeGreaterThanOrEqualTo(0u);
response.StartTime.ShouldBe(DateTimeOffset.UtcNow, TimeSpan.FromMinutes(5));
response.ReadBytes.ShouldBeGreaterThanOrEqualTo(0u);
response.WrittenBytes.ShouldBeGreaterThanOrEqualTo(0u);
response.MessagesSizeBytes.ShouldBeGreaterThanOrEqualTo(0u);
response.StreamsCount.ShouldBeGreaterThanOrEqualTo(1);
response.TopicsCount.ShouldBeGreaterThanOrEqualTo(1);
response.PartitionsCount.ShouldBeGreaterThanOrEqualTo(1);
response.SegmentsCount.ShouldBeGreaterThanOrEqualTo(1);
response.MessagesCount.ShouldBeGreaterThanOrEqualTo(1u);
response.ClientsCount.ShouldBeGreaterThanOrEqualTo(1);
response.Hostname.ShouldNotBeNullOrEmpty();
response.OsName.ShouldNotBeNullOrEmpty();
response.OsVersion.ShouldNotBeNullOrEmpty();
response.KernelVersion.ShouldNotBeNullOrEmpty();
response.IggyServerVersion.ShouldNotBeNullOrEmpty();
response.IggyServerSemver.ShouldNotBe(0u);
}
[Test]
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
public async Task Ping_Should_Pong(Protocol protocol)
{
var client = await Fixture.CreateAuthenticatedClient(protocol);
await Should.NotThrowAsync(client.PingAsync());
}
[Test]
[MethodDataSource<IggyServerFixture>(nameof(IggyServerFixture.ProtocolData))]
public async Task GetSnapshot_Should_Return_ValidZipData(Protocol protocol)
{
var client = await Fixture.CreateAuthenticatedClient(protocol);
var snapshot = await client.GetSnapshotAsync(
SnapshotCompression.Deflated,
[SystemSnapshotType.Test]);
snapshot.ShouldNotBeNull();
snapshot.Length.ShouldBeGreaterThan(0);
// Verify it's a valid ZIP archive by checking the ZIP magic bytes (PK\x03\x04)
snapshot[0].ShouldBe((byte)'P');
snapshot[1].ShouldBe((byte)'K');
}
}