Skip to content

Commit

Permalink
fix: make optional properties of bindings nullable (#89)
Browse files Browse the repository at this point in the history
Co-authored-by: Alex Wichmann <[email protected]>
Co-authored-by: Alex Wichmann <[email protected]>
  • Loading branch information
3 people authored Mar 1, 2023
1 parent 81261ad commit 499cf64
Show file tree
Hide file tree
Showing 7 changed files with 185 additions and 13 deletions.
20 changes: 20 additions & 0 deletions src/LEGO.AsyncAPI.Readers/ParseNodes/ParseNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,21 +94,41 @@ public virtual string GetScalarValue()
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual string GetScalarValueOrDefault(string defaultValue)
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual bool GetBooleanValue()
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual bool? GetBooleanValueOrDefault(bool? defaultValue)
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual int GetIntegerValue()
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual int? GetIntegerValueOrDefault(int? defaultValue)
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual long GetLongValue()
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual long? GetLongValueOrDefault(long? defaultValue)
{
throw new AsyncApiReaderException("Cannot create a scalar value from this type of node.", this.Context);
}

public virtual List<IAsyncApiAny> CreateListOfAny()
{
throw new AsyncApiReaderException("Cannot create a list from this type of node.", this.Context);
Expand Down
40 changes: 40 additions & 0 deletions src/LEGO.AsyncAPI.Readers/ParseNodes/ValueNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,16 @@ public override string GetScalarValue()
return this.node.Value;
}

public override string GetScalarValueOrDefault(string defaultValue)
{
if (this.node.Value is not null)
{
return this.node.Value;
}

return defaultValue;
}

public override int GetIntegerValue()
{
if (int.TryParse(this.node.Value, out int value))
Expand All @@ -39,6 +49,16 @@ public override int GetIntegerValue()
throw new AsyncApiReaderException("Value could not parse to integer", this.node);
}

public override int? GetIntegerValueOrDefault(int? defaultValue)
{
if (int.TryParse(this.node.Value, out int value))
{
return value;
}

return defaultValue;
}

public override long GetLongValue()
{
if (long.TryParse(this.node.Value, out long value))
Expand All @@ -49,6 +69,16 @@ public override long GetLongValue()
throw new AsyncApiReaderException("Value could not parse to long", this.node);
}

public override long? GetLongValueOrDefault(long? defaultValue)
{
if (long.TryParse(this.node.Value, out long value))
{
return value;
}

return defaultValue;
}

public override bool GetBooleanValue()
{
if (bool.TryParse(this.node.Value, out bool value))
Expand All @@ -59,6 +89,16 @@ public override bool GetBooleanValue()
throw new AsyncApiReaderException("Value could not parse to bool", this.node);
}

public override bool? GetBooleanValueOrDefault(bool? defaultValue)
{
if (bool.TryParse(this.node.Value, out bool value))
{
return value;
}

return defaultValue;
}

public override IAsyncApiAny CreateAny()
{
var value = this.GetScalarValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ public class KafkaChannelBinding : IChannelBinding
/// <summary>
/// Number of partitions configured on this topic (useful to know how many parallel consumers you may run).
/// </summary>
public int Partitions { get; set; }
public int? Partitions { get; set; }

/// <summary>
/// Number of replicas configured on this topic.
/// </summary>
public int Replicas { get; set; }
public int? Replicas { get; set; }

/// <summary>
/// Topic configuration properties that are relevant for the API.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,22 @@ public class TopicConfigurationObject : IAsyncApiElement
/// <summary>
/// The retention.ms configuration option.
/// </summary>
public int RetentionMiliseconds { get; set; }
public int? RetentionMiliseconds { get; set; }

/// <summary>
/// The retention.bytes configuration option.
/// </summary>
public int RetentionBytes { get; set; }
public int? RetentionBytes { get; set; }

/// <summary>
/// The delete.retention.ms configuration option.
/// </summary>
public int DeleteRetentionMiliseconds { get; set; }
public int? DeleteRetentionMiliseconds { get; set; }

/// <summary>
/// The max.message.bytes configuration option.
/// </summary>
public int MaxMessageBytes { get; set; }
public int? MaxMessageBytes { get; set; }

public void Serialize(IAsyncApiWriter writer)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ public class PulsarChannelBinding : IChannelBinding
/// <summary>
/// persistence of the topic in Pulsar persistent or non-persistent.
/// </summary>
public Persistence Persistence { get; set; }
public Persistence? Persistence { get; set; }

/// <summary>
/// Topic compaction threshold given in bytes.
/// </summary>
public int Compaction { get; set; }
public int? Compaction { get; set; }

/// <summary>
/// A list of clusters the topic is replicated to.
Expand All @@ -40,12 +40,12 @@ public class PulsarChannelBinding : IChannelBinding
/// <summary>
/// Message Time-to-live in seconds.
/// </summary>
public int TTL { get; set; }
public int? TTL { get; set; }

/// <summary>
/// When Message deduplication is enabled, it ensures that each message produced on Pulsar topics is persisted to disk only once.
/// </summary>
public bool Deduplication { get; set; }
public bool? Deduplication { get; set; }

/// <summary>
/// The version of this binding.
Expand Down
114 changes: 113 additions & 1 deletion test/LEGO.AsyncAPI.Tests/Bindings/Pulsar/PulsarBindings_Should.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
namespace LEGO.AsyncAPI.Tests.Bindings.Pulsar
using LEGO.AsyncAPI.Models.Bindings;

namespace LEGO.AsyncAPI.Tests.Bindings.Pulsar
{
using FluentAssertions;
using LEGO.AsyncAPI.Models;
Expand Down Expand Up @@ -64,6 +66,44 @@ public void PulsarChannelBinding_WithFilledObject_SerializesAndDeserializes()
binding.Should().BeEquivalentTo(channel);
}

[Test]
public void PulsarChannelBindingNamespaceDefaultToNull()
{
// Arrange
var actual =
@"bindings:
pulsar:
persistence: persistent";

// Act
// Assert
var binding = new AsyncApiStringReader().ReadFragment<AsyncApiChannel>(actual, AsyncApiVersion.AsyncApi2_0, out _);

Assert.AreEqual(null, ((PulsarChannelBinding)binding.Bindings[BindingType.Pulsar]).Namespace);
}

[Test]
public void PulsarChannelBindingPropertiesExceptNamespaceDefaultToNull()
{
// Arrange
var actual =
@"bindings:
pulsar:
namespace: staging";

// Act
// Assert
var binding = new AsyncApiStringReader().ReadFragment<AsyncApiChannel>(actual, AsyncApiVersion.AsyncApi2_0, out _);
var pulsarBinding = ((PulsarChannelBinding) binding.Bindings[BindingType.Pulsar]);

Assert.AreEqual(null, pulsarBinding.Persistence);
Assert.AreEqual(null, pulsarBinding.Compaction);
Assert.AreEqual(null, pulsarBinding.GeoReplication);
Assert.AreEqual(null, pulsarBinding.Retention);
Assert.AreEqual(null, pulsarBinding.TTL);
Assert.AreEqual(null, pulsarBinding.Deduplication);
}

[Test]
public void PulsarServerBinding_WithFilledObject_SerializesAndDeserializes()
{
Expand Down Expand Up @@ -97,5 +137,77 @@ public void PulsarServerBinding_WithFilledObject_SerializesAndDeserializes()
Assert.AreEqual(actual, expected);
binding.Should().BeEquivalentTo(server);
}

[Test]
public void ServerBindingVersionDefaultsToNull()
{
// Arrange
var expected =
@"url: https://example.com
protocol: pulsar
bindings:
pulsar:
tenant: contoso";

var server = new AsyncApiServer()
{
Url = "https://example.com",
Protocol = "pulsar",
};

server.Bindings.Add(new PulsarServerBinding
{
Tenant = "contoso",
BindingVersion = null,
});

// Act
var actual = server.SerializeAsYaml(AsyncApiVersion.AsyncApi2_0);
actual = actual.MakeLineBreaksEnvironmentNeutral();
expected = expected.MakeLineBreaksEnvironmentNeutral();

var binding = new AsyncApiStringReader().ReadFragment<AsyncApiServer>(actual, AsyncApiVersion.AsyncApi2_0, out _);

// Assert
Assert.AreEqual(actual, expected);
Assert.AreEqual(null, ((PulsarServerBinding)binding.Bindings[BindingType.Pulsar]).BindingVersion);
binding.Should().BeEquivalentTo(server);
}

[Test]
public void ServerTenantDefaultsToNull()
{
// Arrange
var expected =
@"url: https://example.com
protocol: pulsar
bindings:
pulsar:
bindingVersion: latest";

var server = new AsyncApiServer()
{
Url = "https://example.com",
Protocol = "pulsar",
};

server.Bindings.Add(new PulsarServerBinding
{
Tenant = null,
BindingVersion = "latest",
});

// Act
var actual = server.SerializeAsYaml(AsyncApiVersion.AsyncApi2_0);
actual = actual.MakeLineBreaksEnvironmentNeutral();
expected = expected.MakeLineBreaksEnvironmentNeutral();

var binding = new AsyncApiStringReader().ReadFragment<AsyncApiServer>(actual, AsyncApiVersion.AsyncApi2_0, out _);

// Assert
Assert.AreEqual(actual, expected);
Assert.AreEqual(null, ((PulsarServerBinding)binding.Bindings[BindingType.Pulsar]).Tenant);
binding.Should().BeEquivalentTo(server);
}
}
}
4 changes: 2 additions & 2 deletions test/LEGO.AsyncAPI.Tests/Models/AsyncApiMessage_Should.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,10 @@ public void AsyncApiMessage_WithSchemaFormat_Serializes()
type:
- string
- 'null'
schemaFormat: application/vnd.aai.asyncapi+json;version=2.5.0";
schemaFormat: application/vnd.aai.asyncapi+json;version=2.6.0";

var message = new AsyncApiMessage();
message.SchemaFormat = "application/vnd.aai.asyncapi+json;version=2.5.0";
message.SchemaFormat = "application/vnd.aai.asyncapi+json;version=2.6.0";
message.Payload = new AsyncApiSchema()
{
Properties = new Dictionary<string, AsyncApiSchema>()
Expand Down

0 comments on commit 499cf64

Please sign in to comment.