Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #37

Merged
merged 4 commits into from
Jul 31, 2024
Merged

Dev #37

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions MK.IO.Tests/AssetsOperationsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,53 @@ public void Create_DeserializationError(string json)
// Assert
mockClient2.Verify(); // Verify that CreateOrUpdateAsync was called as expected
}

[Theory]
[InlineData(256,33)]
[InlineData(257,32)]
public void Create_AssetErrorInTags(int sizeValue, int numberEntries)
{
// Arrange
var assetsOperations = new AssetsOperations(mockClient.Object);

var tags = new Dictionary<string, string>();
for (int i = 0; i < numberEntries; i++)
{
tags.Add(MKIOClient.GenerateUniqueName(null, sizeValue), MKIOClient.GenerateUniqueName(null, sizeValue));
}

// act & assert
Assert.Throws<ArgumentException>(() => assetsOperations.CreateOrUpdate("name", "containername", "storagename", labels: tags));
}

[Theory]
[InlineData(256, 32)]
public void Create_AssetNoErrorInTags(int sizeValue, int numberEntries)
{
var mockClient2 = new Mock<MKIOClient>("subscriptionname", Constants.jwtFakeToken);

var tags = new Dictionary<string, string>();
for (int i = 0; i < numberEntries; i++)
{
tags.Add(MKIOClient.GenerateUniqueName(null, sizeValue), MKIOClient.GenerateUniqueName(null, sizeValue));
}

mockClient2.Setup(client => client.CreateObjectPutAsync(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<CancellationToken>()
)
)
.Returns(Task.FromResult("{}"))
.Verifiable("CreateObjectPutAsync was not called with the expected parameters.");

var mop = new Mock<AssetsOperations>(mockClient2.Object);

// Act
mop.Object.CreateOrUpdate("name", "containername", "storagename", labels: tags);

// Assert
mockClient2.Verify(); // Verify that CreateOrUpdateAsync was called as expected
}
}
}
246 changes: 246 additions & 0 deletions MK.IO.Tests/LiveEventsOperationsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,246 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Moq;
using MK.IO.Models;
using MK.IO.Operations;
using Newtonsoft.Json;
using System.Xml.Linq;

namespace MK.IO.Tests
{
public class LiveEventsOperationsTests
{
private Mock<MKIOClient> _mockClient;
private readonly LiveEventProperties _properties;

public LiveEventsOperationsTests()
{
_mockClient = new Mock<MKIOClient>("subscriptionname", Constants.jwtFakeToken);
_properties = new LiveEventProperties()
{
Encoding = new LiveEventEncoding { EncodingType = LiveEventEncodingType.PassthroughBasic }
};

_mockClient.Setup(client => client.CreateObjectPutAsync(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<CancellationToken>()
)
)
.Returns(Task.FromResult("{}"))
.Verifiable("CreateObjectPutAsync was not called with the expected parameters.");
}

[Theory]
[InlineData(null)]
public void Create_WithNull(string name)
{
// Arrange
var liveEventsOperations = new LiveEventsOperations(_mockClient.Object);

// act & assert
Assert.Throws<ArgumentNullException>(() => liveEventsOperations.Create(name, "name", _properties));
Assert.Throws<ArgumentNullException>(() => liveEventsOperations.Create("name", name, _properties));
Assert.Throws<ArgumentNullException>(() => liveEventsOperations.Create("name", "name", null));
}

[Theory]
[InlineData("")]
public void Create_WithEmpty(string name)
{
// Arrange
var liveEventsOperations = new LiveEventsOperations(_mockClient.Object);

// act & assert
Assert.Throws<ArgumentException>(() => liveEventsOperations.Create(name, "name", _properties));
Assert.Throws<ArgumentException>(() => liveEventsOperations.Create("name", name, _properties));
}

[Theory]
[InlineData("name")]
public void Create_LiveEventSRTWithPasstroughError(string name)
{
// Arrange
var liveEventsOperations = new LiveEventsOperations(_mockClient.Object);

var prop = new LiveEventProperties()
{
Encoding = new LiveEventEncoding { EncodingType = LiveEventEncodingType.PassthroughBasic },
Input = new LiveEventInput { StreamingProtocol = LiveEventInputProtocol.SRT }
};

// act & assert
Assert.Throws<ArgumentException>(() => liveEventsOperations.Create(name, "francecentral", prop));
}

[Theory]
[InlineData("name")]
public void Create_LiveEventWithoutEncodingPropError(string name)
{
// Arrange
var liveEventsOperations = new LiveEventsOperations(_mockClient.Object);

var prop = new LiveEventProperties()
{
Input = new LiveEventInput { StreamingProtocol = LiveEventInputProtocol.SRT }
};

// act & assert
Assert.Throws<ArgumentException>(() => liveEventsOperations.Create(name, "francecentral", prop));
}

[Theory]
[InlineData("name")]
public async Task Create_LiveEventSRTWithEncodingOK(string name)
{
// Arrange
var liveEventsOperations = new LiveEventsOperations(_mockClient.Object);

var mop = new Mock<LiveEventsOperations>(_mockClient.Object);

var prop = new LiveEventProperties()
{
Encoding = new LiveEventEncoding { EncodingType = LiveEventEncodingType.Premium1080p },
Input = new LiveEventInput { StreamingProtocol = LiveEventInputProtocol.SRT },
};

// Act
await mop.Object.CreateAsync(name, "francecentral", prop);

// Assert
mop.Verify(); // Verify that CreateOrUpdateAsync was called as expected
}

[Theory]
[InlineData("n")] // 1 char
[InlineData("name with space")]
[InlineData("2VQTsvohfWXqDiBTPaHoSHm9Zt4dbKWlb")] // 33 chars
public void Create_LiveEventErrorInName(string name)
{
// Arrange
var liveEventsOperations = new LiveEventsOperations(_mockClient.Object);

// act & assert
Assert.Throws<ArgumentException>(() => liveEventsOperations.Create(name, "francecentral", _properties));
}

[Theory]
[InlineData("n1")]
[InlineData("name-123")]
[InlineData("name_123")]
[InlineData("name.123")]
[InlineData("nname--123")]
[InlineData("2VQTsvohfWXqDiBTPaHoSHm9Zt4dbKWl")] // 32 chars
public async Task Create_LiveEventNameOK(string name)
{
// Arrange
var liveEventsOperations = new LiveEventsOperations(_mockClient.Object);

var mop = new Mock<LiveEventsOperations>(_mockClient.Object);

// Act
await mop.Object.CreateAsync(name, "francecentral", _properties);

// Assert
mop.Verify(); // Verify that CreateOrUpdateAsync was called as expected
}

[Theory]
[InlineData("{\"name\":\"liveevent-6de535d0\",\"id\":\"/subscriptions/52907a2e-ab43-43ba-8b9f-8cb78285f665/resourceGroups/default/providers/Microsoft.Media/mediaservices/mkiotest/liveEvents/liveevent-6de535d0\",\"type\":\"Microsoft.Media/mediaservices/liveevents\",\"location\":\"francecentral\",\"tags\":{},\"properties\":{\"created\":\"2024-06-26T20:37:45.398939Z\",\"lastModified\":\"2024-07-23T08:02:06.178290Z\",\"useStaticHostname\":false,\"streamOptions\":[\"Default\"],\"input\":{\"accessControl\":{\"ip\":{\"allow\":[{\"name\":\"everyone\",\"address\":\"0.0.0.0\",\"subnetPrefixLength\":0}]}},\"endpoints\":[{\"url\":\"rtmp://in-742d58f3-3492-4909-a7d2-965a61157b10.francecentral.streaming.mediakind.com:1935/0dcea5b2-4eed-4e80-8e37-df951aa9138d\",\"protocol\":\"RTMP\"}],\"keyFrameIntervalDuration\":\"PT2S\",\"streamingProtocol\":\"RTMP\",\"accessToken\":\"0dcea5b2-4eed-4e80-8e37-df951aa9138d\"},\"encoding\":{\"encodingType\":\"PassthroughBasic\",\"presetName\":\"\",\"keyFrameInterval\":\"PT2S\",\"stretchMode\":\"AutoSize\"},\"crossSiteAccessPolicies\":{\"clientAccessPolicy\":null,\"crossDomainPolicy\":null},\"provisioningState\":\"Succeeded\",\"resourceState\":\"Stopped\",\"preview\":{\"accessControl\":{\"ip\":{\"allow\":[]}},\"streamingPolicyName\":\"Predefined_ClearStreamingOnly\",\"previewLocator\":\"03e93aca-0576-40e2-92c3-ce2f0f100998\",\"endpoints\":[{\"url\":\"https://liveevent-6de535d0-mkiotest-preview.francecentral.streaming.mediakind.com/03e93aca-0576-40e2-92c3-ce2f0f100998/manifest.mpd\",\"protocol\":\"FragmentedMP4\"}]}},\"systemData\":{\"createdBy\":\"[email protected]\",\"createdByType\":\"User\",\"createdAt\":\"2024-06-26T20:37:45.398939Z\",\"lastModifiedBy\":\"[email protected]\",\"lastModifiedByType\":\"User\",\"lastModifiedAt\":\"2024-07-23T08:02:06.178290Z\"},\"supplemental\":{\"operation\":\"get\",\"subscription\":{\"id\":\"bf747f59-771a-4e9b-a6cd-59351c4a71d2\",\"name\":\"mkiotest\"}}}")]
[InlineData("{\"name\":\"liveevent-srt\",\"id\":\"/subscriptions/52907a2e-ab43-43ba-8b9f-8cb78285f665/resourceGroups/default/providers/Microsoft.Media/mediaservices/mkiotest/liveEvents/liveevent-srt\",\"type\":\"Microsoft.Media/mediaservices/liveevents\",\"location\":\"francecentral\",\"tags\":{},\"properties\":{\"created\":\"2024-07-24T04:07:50.363640Z\",\"lastModified\":\"2024-07-24T04:08:23.339112Z\",\"useStaticHostname\":false,\"streamOptions\":[\"Default\"],\"input\":{\"accessControl\":{\"ip\":{\"allow\":[{\"name\":\"AllowAll\",\"address\":\"0.0.0.0\",\"subnetPrefixLength\":0}]}},\"endpoints\":[{\"url\":\"srt://in-35b482ce-0a1a-41f6-88aa-47dcf590d3c5.francecentral.streaming.mediakind.com:6000?passphrase=abcdgdhfqsfh45gdsqsdksdfn&pkbkeylen=16\",\"protocol\":\"SRT\"}],\"keyFrameIntervalDuration\":\"PT2S\",\"streamingProtocol\":\"SRT\",\"accessToken\":\"abcdgdhfqsfh45gdsqsdksdfn\"},\"encoding\":{\"encodingType\":\"Standard\",\"presetName\":\"Default720p\",\"keyFrameInterval\":\"PT2S\",\"stretchMode\":\"AutoSize\"},\"crossSiteAccessPolicies\":{\"clientAccessPolicy\":null,\"crossDomainPolicy\":null},\"provisioningState\":\"Succeeded\",\"resourceState\":\"Stopped\",\"preview\":{\"accessControl\":{\"ip\":{\"allow\":[{\"name\":\"AllowAll\",\"address\":\"0.0.0.0\",\"subnetPrefixLength\":0}]}},\"streamingPolicyName\":\"Predefined_ClearStreamingOnly\",\"previewLocator\":\"9550a87c-2561-4073-8c81-167418bcea89\",\"endpoints\":[{\"url\":\"https://liveevent-srt-mkiotest-preview.francecentral.streaming.mediakind.com/9550a87c-2561-4073-8c81-167418bcea89/manifest.mpd\",\"protocol\":\"FragmentedMP4\"}]}},\"systemData\":{\"createdBy\":\"[email protected]\",\"createdByType\":\"User\",\"createdAt\":\"2024-07-24T04:07:50.363640Z\",\"lastModifiedBy\":\"[email protected]\",\"lastModifiedByType\":\"User\",\"lastModifiedAt\":\"2024-07-24T04:08:23.339112Z\"},\"supplemental\":{\"operation\":\"get\",\"subscription\":{\"id\":\"bf747f59-771a-4e9b-a6cd-59351c4a71d2\",\"name\":\"mkiotest\"}}}")]
public async Task Create_DeserializationOK(string json)
{
var mockClient2 = new Mock<MKIOClient>("subscriptionname", Constants.jwtFakeToken);

mockClient2.Setup(client => client.CreateObjectPutAsync(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<CancellationToken>()
)
)
.Returns(Task.FromResult(json))
.Verifiable("CreateObjectPutAsync was not called with the expected parameters.");

var mop = new Mock<LiveEventsOperations>(mockClient2.Object);

// Act
await mop.Object.CreateAsync("name", "name", _properties);

// Assert
mop.Verify();
}

[Theory]
[InlineData("{\"name\":\"liveevent-6de535d0\",\"id\":\"/subscriptions/52907a2e-ab43-43ba-8b9f-8cb78285f665/resourceGroups/default/providers/Microsoft.Media/mediaservices/mkiotest/liveEvents/liveevent-6de535d0\",\"type\":\"Microsoft.Media/mediaservices/liveevents\",\"location\":\"francecentral\",\"tags\":{},\"properties\":{\"created\":\"2024-06-26T20:37:45.398939Z\",\"lastModified\":\"2024-07-23T08:02:06.178290Z\",\"useStaticHostname\":false,\"streamOptions\":[\"Default\"],\"input\":{\"accessControl\":{\"ip\":{\"allow\":[{\"name\":\"everyone\",\"address\":\"0.0.0.0\",\"subnetPrefixLength\":0}]}},\"endpoints\":[{\"url\":\"rtmp://in-742d58f3-3492-4909-a7d2-965a61157b10.francecentral.streaming.mediakind.com:1935/0dcea5b2-4eed-4e80-8e37-df951aa9138d\",\"protocol\":\"RTMP\"}],\"keyFrameIntervalDuration\":\"PT2S\",\"streamingProtocol\":\"RTMPERROR\",\"accessToken\":\"0dcea5b2-4eed-4e80-8e37-df951aa9138d\"},\"encoding\":{\"encodingType\":\"PassthroughBasic\",\"presetName\":\"\",\"keyFrameInterval\":\"PT2S\",\"stretchMode\":\"AutoSize\"},\"crossSiteAccessPolicies\":{\"clientAccessPolicy\":null,\"crossDomainPolicy\":null},\"provisioningState\":\"Succeeded\",\"resourceState\":\"Stopped\",\"preview\":{\"accessControl\":{\"ip\":{\"allow\":[]}},\"streamingPolicyName\":\"Predefined_ClearStreamingOnly\",\"previewLocator\":\"03e93aca-0576-40e2-92c3-ce2f0f100998\",\"endpoints\":[{\"url\":\"https://liveevent-6de535d0-mkiotest-preview.francecentral.streaming.mediakind.com/03e93aca-0576-40e2-92c3-ce2f0f100998/manifest.mpd\",\"protocol\":\"FragmentedMP4\"}]}},\"systemData\":{\"createdBy\":\"[email protected]\",\"createdByType\":\"User\",\"createdAt\":\"2024-06-26T20:37:45.398939Z\",\"lastModifiedBy\":\"[email protected]\",\"lastModifiedByType\":\"User\",\"lastModifiedAt\":\"2024-07-23T08:02:06.178290Z\"},\"supplemental\":{\"operation\":\"get\",\"subscription\":{\"id\":\"bf747f59-771a-4e9b-a6cd-59351c4a71d2\",\"name\":\"mkiotest\"}}}")]
public void Create_DeserializationError(string json)
{
var mockClient2 = new Mock<MKIOClient>("subscriptionname", Constants.jwtFakeToken);

mockClient2.Setup(client => client.CreateObjectPutAsync(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<CancellationToken>()
)
)
.Returns(Task.FromResult(json))
.Verifiable("CreateObjectPutAsync was not called with the expected parameters.");

var mop = new Mock<LiveEventsOperations>(mockClient2.Object);

// act & assert
Assert.Throws<JsonSerializationException>(() => mop.Object.Create("name", "name", _properties));

// Assert
mop.Verify();
}

[Theory]
[InlineData(64, 17)]
[InlineData(65, 16)]
public void Create_LiveEventErrorInTags(int sizeValue, int numberEntries)
{
// Arrange
var liveEventsOperations = new LiveEventsOperations(_mockClient.Object);

var tags = new Dictionary<string, string>();
for (int i = 0; i < numberEntries; i++)
{
tags.Add(MKIOClient.GenerateUniqueName(null, sizeValue), MKIOClient.GenerateUniqueName(null, sizeValue));
}

// act & assert
Assert.Throws<ArgumentException>(() => liveEventsOperations.Create("name", "francecentral", _properties, tags));
}

[Theory]
[InlineData(64, 16)]
public void Create_LiveEventNoErrorInTags(int sizeValue, int numberEntries)
{
var mockClient2 = new Mock<MKIOClient>("subscriptionname", Constants.jwtFakeToken);

mockClient2.Setup(client => client.CreateObjectPutAsync(
It.IsAny<string>(),
It.IsAny<string>(),
It.IsAny<CancellationToken>()
)
)
.Returns(Task.FromResult("{}"))
.Verifiable("CreateObjectPutAsync was not called with the expected parameters.");

var mop = new Mock<LiveEventsOperations>(mockClient2.Object);

var tags = new Dictionary<string, string>();
for (int i = 0; i < numberEntries; i++)
{
tags.Add(MKIOClient.GenerateUniqueName(null, sizeValue), MKIOClient.GenerateUniqueName(null, sizeValue));
}

// Act
mop.Object.Create("name", "name", _properties, tags);

// Assert
mop.Verify();
}
}
}
39 changes: 34 additions & 5 deletions MK.IO/Argument.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using System.IdentityModel.Tokens.Jwt;
using Microsoft.IdentityModel.JsonWebTokens;
using System.Text.RegularExpressions;

namespace MK.IO
Expand Down Expand Up @@ -72,6 +72,21 @@ public static void AssertNotMoreThanLength(string? value, string name, int lengt
}
}

/// <summary>
/// Asserts that the value does not have a length lower than the specified value.
/// </summary>
/// <param name="value"></param>
/// <param name="name"></param>
/// <param name="length"></param>
/// <exception cref="ArgumentException"></exception>
public static void AssertNotLessThanLength(string? value, string name, int length)
{
if (value != null && value.Length < length)
{
throw new ArgumentException($"Value length cannot be less than {length}.", name);
}
}

/// <summary>
/// Assert that value is conform to regex pattern.
/// </summary>
Expand All @@ -95,13 +110,27 @@ public static void AssertRespectRegex(string? value, string name, string regexPa
/// <exception cref="ArgumentException"></exception>
public static void AssertJwtToken(string authToken, string name)
{
try
var jsonWebTokenHandler = new JsonWebTokenHandler();
if (!jsonWebTokenHandler.CanReadToken(authToken))
{
var jwtSecurityToken = new JwtSecurityToken(authToken);
throw new ArgumentException("Value is not a JWT Token. Please read https://docs.mk.io/docs/personal-access-tokens to learn how to generate a personal access token.", name);
}
catch (Exception ex)
}

internal static void AssertTagsNullOrCompliant(Dictionary<string, string>? tags, int maxNumber, int maxLength)
{
if (tags != null)
{
throw new ArgumentException("Value is not a JWT Token. Please read https://docs.mk.io/docs/personal-access-tokens to learn how to generate a personal access token.", name);
if (tags.Count > maxNumber)
{
throw new ArgumentException($"Tags are limited to {maxNumber} entries.");
}

foreach (var tag in tags)
{
AssertNotMoreThanLength(tag.Key, "tag.Key", maxLength);
AssertNotMoreThanLength(tag.Value, "tag.Value", maxLength);
}
}
}
}
Expand Down
Loading
Loading