Skip to content

Commit 52ac190

Browse files
authored
Misc fixes and unit test additions (#219)
* Fixes * Unit tests * Fix null ref error when source name is not found
1 parent c87cfde commit 52ac190

13 files changed

+1230
-30
lines changed

src/Sleet/Program.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace Sleet
88
{
99
public class Program
1010
{
11-
public static int Main(string[] args)
11+
public static async Task<int> Main(string[] args)
1212
{
1313
var logLevel = Util.DefaultLogLevel;
1414

@@ -19,8 +19,7 @@ public static int Main(string[] args)
1919

2020
using (var log = new ConsoleLogger(logLevel))
2121
{
22-
var task = MainCore(args, log);
23-
return task.Result;
22+
return await MainCore(args, log).ConfigureAwait(false);
2423
}
2524
}
2625

src/SleetLib/AssemblyVersionHelper.cs

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,39 +6,51 @@ namespace Sleet
66
{
77
public static class AssemblyVersionHelper
88
{
9+
private static volatile SemanticVersion _versionOverride;
10+
private static volatile SemanticVersion _version;
11+
private static readonly object _lock = new object();
12+
913
/// <summary>
1014
/// Set this to override the assembly version.
1115
/// </summary>
12-
public static SemanticVersion VersionOverride { get; set; }
13-
14-
private static SemanticVersion _version;
16+
public static SemanticVersion VersionOverride
17+
{
18+
get => _versionOverride;
19+
set => _versionOverride = value;
20+
}
1521

1622
/// <summary>
1723
/// Read the assembly version or override.
1824
/// </summary>
1925
/// <returns></returns>
2026
public static SemanticVersion GetVersion()
2127
{
22-
if (VersionOverride != null)
28+
if (_versionOverride != null)
2329
{
24-
return VersionOverride;
30+
return _versionOverride;
2531
}
2632

2733
if (_version == null)
2834
{
29-
// Read the assembly
30-
var assemblyVersion = typeof(AssemblyVersionHelper).GetTypeInfo().Assembly.GetName().Version;
31-
32-
// Avoid going lower than 3.0.0. This can happen in some build environments and will fail tests.
33-
var lowestPossible = new SemanticVersion(3, 0, 0);
34-
var tempVersion = new SemanticVersion(Math.Max(0, assemblyVersion.Major), Math.Max(0, assemblyVersion.Minor), Math.Max(0, assemblyVersion.Build));
35-
36-
if (tempVersion < lowestPossible)
35+
lock (_lock)
3736
{
38-
tempVersion = lowestPossible;
37+
if (_version == null)
38+
{
39+
// Read the assembly
40+
var assemblyVersion = typeof(AssemblyVersionHelper).GetTypeInfo().Assembly.GetName().Version;
41+
42+
// Avoid going lower than 3.0.0. This can happen in some build environments and will fail tests.
43+
var lowestPossible = new SemanticVersion(3, 0, 0);
44+
var tempVersion = new SemanticVersion(Math.Max(0, assemblyVersion.Major), Math.Max(0, assemblyVersion.Minor), Math.Max(0, assemblyVersion.Build));
45+
46+
if (tempVersion < lowestPossible)
47+
{
48+
tempVersion = lowestPossible;
49+
}
50+
51+
_version = tempVersion;
52+
}
3953
}
40-
41-
_version = tempVersion;
4254
}
4355

4456
return _version;

src/SleetLib/ExternalSearchHandler.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ public Task UnSet()
3737
private async Task SetSearchUri(string value)
3838
{
3939
var indexFile = _context.Source.Get("index.json");
40-
var json = await indexFile.GetJson(_context.Log, _context.Token);
40+
var json = await indexFile.GetJson(_context.Log, _context.Token).ConfigureAwait(false);
4141
var searchEntry = GetSearchEntry(json);
4242
searchEntry["@id"] = value;
43-
await indexFile.Write(json, _context.Log, _context.Token);
43+
await indexFile.Write(json, _context.Log, _context.Token).ConfigureAwait(false);
4444
}
4545

4646
private JObject GetSearchEntry(JObject serviceIndex)

src/SleetLib/FileSystem/AmazonS3File.cs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
100100
{
101101
Stream writeStream = cache;
102102
string contentType = null, contentEncoding = null;
103+
bool disposeWriteStream = false;
104+
103105
if (key.EndsWith(".nupkg", StringComparison.Ordinal))
104106
{
105107
contentType = "application/zip";
@@ -121,6 +123,7 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
121123
{
122124
contentEncoding = "gzip";
123125
writeStream = await JsonUtility.GZipAndMinifyAsync(cache);
126+
disposeWriteStream = true;
124127
}
125128
}
126129
else if (key.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)
@@ -141,10 +144,18 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
141144
log.LogWarning($"Unknown file type: {absoluteUri}");
142145
}
143146

144-
await UploadFileAsync(client, bucketName, key, contentType, contentEncoding, writeStream, serverSideEncryptionMethod, acl, disablePayloadSigning, token)
145-
.ConfigureAwait(false);
146-
147-
writeStream.Dispose();
147+
try
148+
{
149+
await UploadFileAsync(client, bucketName, key, contentType, contentEncoding, writeStream, serverSideEncryptionMethod, acl, disablePayloadSigning, token)
150+
.ConfigureAwait(false);
151+
}
152+
finally
153+
{
154+
if (disposeWriteStream && writeStream != cache)
155+
{
156+
writeStream.Dispose();
157+
}
158+
}
148159
}
149160
}
150161

src/SleetLib/FileSystem/AzureFile.cs

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
5858
using (var cache = LocalCacheFile.OpenRead())
5959
{
6060
Stream writeStream = cache;
61+
bool disposeWriteStream = false;
6162
var blobHeaders = new BlobHttpHeaders
6263
{
6364
CacheControl = "no-store"
@@ -85,6 +86,7 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
8586
{
8687
blobHeaders.ContentEncoding = "gzip";
8788
writeStream = await JsonUtility.GZipAndMinifyAsync(cache);
89+
disposeWriteStream = true;
8890
}
8991
}
9092
else if (_blob.Uri.AbsoluteUri.EndsWith(".dll", StringComparison.OrdinalIgnoreCase)
@@ -105,9 +107,17 @@ protected override async Task CopyToSource(ILogger log, CancellationToken token)
105107
log.LogWarning($"Unknown file type: {_blob.Uri.AbsoluteUri}");
106108
}
107109

108-
await _blob.UploadAsync(writeStream, blobHeaders, cancellationToken: token);
109-
110-
writeStream.Dispose();
110+
try
111+
{
112+
await _blob.UploadAsync(writeStream, blobHeaders, cancellationToken: token);
113+
}
114+
finally
115+
{
116+
if (disposeWriteStream && writeStream != cache)
117+
{
118+
writeStream.Dispose();
119+
}
120+
}
111121
}
112122
}
113123
else if (await _blob.ExistsAsync(token))

src/SleetLib/FileSystem/FileSystemFactory.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public static async Task<ISleetFileSystem> CreateFileSystemAsync(LocalSettings s
3434
{
3535
var sourceName = JsonUtility.GetValueCaseInsensitive(sourceEntry, "name");
3636

37-
if (source.Equals(sourceName, StringComparison.OrdinalIgnoreCase))
37+
if (source?.Equals(sourceName, StringComparison.OrdinalIgnoreCase) == true)
3838
{
3939
var path = JsonUtility.GetValueCaseInsensitive(sourceEntry, "path");
4040
var baseURIString = JsonUtility.GetValueCaseInsensitive(sourceEntry, "baseURI");

src/SleetLib/TemplateUtility.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ public static async Task<string> LoadTemplate(string name, DateTimeOffset now, U
1212
{
1313
using (var reader = new StreamReader(GetResource($"template{name}.json")))
1414
{
15-
var data = await reader.ReadToEndAsync();
15+
var data = await reader.ReadToEndAsync().ConfigureAwait(false);
1616

1717
return data
1818
.Replace("$SLEETVERSION$", AssemblyVersionHelper.GetVersion().ToFullVersionString())
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
using System;
2+
using System.IO;
3+
using System.Threading.Tasks;
4+
using FluentAssertions;
5+
using Newtonsoft.Json.Linq;
6+
using NuGet.Common;
7+
using NuGet.Test.Helpers;
8+
using Sleet;
9+
using Xunit;
10+
11+
namespace SleetLib.Tests
12+
{
13+
public class CreateConfigCommandTests
14+
{
15+
[Fact]
16+
public async Task CreateConfigCommand_WithLocalStorageType_CreatesValidConfig()
17+
{
18+
using (var testDir = new TestFolder())
19+
{
20+
var configPath = Path.Combine(testDir.Root, "sleet.json");
21+
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, testDir.Root, NullLogger.Instance);
22+
23+
result.Should().BeTrue();
24+
File.Exists(configPath).Should().BeTrue();
25+
26+
var json = JObject.Parse(File.ReadAllText(configPath));
27+
json["username"].Value<string>().Should().Be("");
28+
json["useremail"].Value<string>().Should().Be("");
29+
json["sources"].Should().NotBeNull();
30+
json["sources"].Count().Should().Be(1);
31+
32+
var source = json["sources"][0];
33+
source["name"].Value<string>().Should().Be("myLocalFeed");
34+
source["type"].Value<string>().Should().Be("local");
35+
source["path"].Value<string>().Should().NotBeNullOrEmpty();
36+
source["baseURI"].Value<string>().Should().Be("https://example.com/feed/");
37+
}
38+
}
39+
40+
[Fact]
41+
public async Task CreateConfigCommand_WithAzureStorageType_CreatesValidConfig()
42+
{
43+
using (var testDir = new TestFolder())
44+
{
45+
var configPath = Path.Combine(testDir.Root, "sleet.json");
46+
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Azure, testDir.Root, NullLogger.Instance);
47+
48+
result.Should().BeTrue();
49+
File.Exists(configPath).Should().BeTrue();
50+
51+
var json = JObject.Parse(File.ReadAllText(configPath));
52+
var source = json["sources"][0];
53+
source["name"].Value<string>().Should().Be("myAzureFeed");
54+
source["type"].Value<string>().Should().Be("azure");
55+
source["container"].Value<string>().Should().Be("myfeed");
56+
source["connectionString"].Value<string>().Should().Be(AzureFileSystem.AzureEmptyConnectionString);
57+
}
58+
}
59+
60+
[Fact]
61+
public async Task CreateConfigCommand_WithS3StorageType_CreatesValidConfig()
62+
{
63+
using (var testDir = new TestFolder())
64+
{
65+
var configPath = Path.Combine(testDir.Root, "sleet.json");
66+
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.S3, testDir.Root, NullLogger.Instance);
67+
68+
result.Should().BeTrue();
69+
File.Exists(configPath).Should().BeTrue();
70+
71+
var json = JObject.Parse(File.ReadAllText(configPath));
72+
var source = json["sources"][0];
73+
source["name"].Value<string>().Should().Be("myAmazonS3Feed");
74+
source["type"].Value<string>().Should().Be("s3");
75+
source["bucketName"].Value<string>().Should().Be("bucketname");
76+
source["region"].Value<string>().Should().Be("us-east-1");
77+
source["profileName"].Value<string>().Should().Be("credentialsFileProfileName");
78+
}
79+
}
80+
81+
[Fact]
82+
public async Task CreateConfigCommand_WithUnspecifiedStorageType_CreatesValidConfig()
83+
{
84+
using (var testDir = new TestFolder())
85+
{
86+
var configPath = Path.Combine(testDir.Root, "sleet.json");
87+
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Unspecified, testDir.Root, NullLogger.Instance);
88+
89+
result.Should().BeTrue();
90+
File.Exists(configPath).Should().BeTrue();
91+
92+
var json = JObject.Parse(File.ReadAllText(configPath));
93+
var source = json["sources"][0];
94+
source["name"].Value<string>().Should().Be("myFeed");
95+
source["type"].Value<string>().Should().Be("");
96+
}
97+
}
98+
99+
[Fact]
100+
public async Task CreateConfigCommand_WithSpecificFileName_CreatesConfigAtPath()
101+
{
102+
using (var testDir = new TestFolder())
103+
{
104+
var configPath = Path.Combine(testDir.Root, "custom-config.json");
105+
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, configPath, NullLogger.Instance);
106+
107+
result.Should().BeTrue();
108+
File.Exists(configPath).Should().BeTrue();
109+
}
110+
}
111+
112+
[Fact]
113+
public async Task CreateConfigCommand_WithExistingFile_ReturnsFalse()
114+
{
115+
using (var testDir = new TestFolder())
116+
{
117+
var configPath = Path.Combine(testDir.Root, "sleet.json");
118+
File.WriteAllText(configPath, "existing content");
119+
120+
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, testDir.Root, NullLogger.Instance);
121+
122+
result.Should().BeFalse();
123+
}
124+
}
125+
126+
[Fact]
127+
public async Task CreateConfigCommand_WithNonExistentDirectory_ReturnsFalse()
128+
{
129+
var nonExistentPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString(), "config.json");
130+
131+
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, nonExistentPath, NullLogger.Instance);
132+
133+
result.Should().BeFalse();
134+
}
135+
136+
[Fact]
137+
public async Task CreateConfigCommand_WithNullOutput_UsesCurrentDirectory()
138+
{
139+
using (var testDir = new TestFolder())
140+
{
141+
var originalDir = Directory.GetCurrentDirectory();
142+
try
143+
{
144+
Directory.SetCurrentDirectory(testDir.Root);
145+
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, null, NullLogger.Instance);
146+
147+
result.Should().BeTrue();
148+
File.Exists(Path.Combine(testDir.Root, "sleet.json")).Should().BeTrue();
149+
}
150+
finally
151+
{
152+
Directory.SetCurrentDirectory(originalDir);
153+
}
154+
}
155+
}
156+
157+
[Fact]
158+
public async Task CreateConfigCommand_WithEmptyOutput_UsesCurrentDirectory()
159+
{
160+
using (var testDir = new TestFolder())
161+
{
162+
var originalDir = Directory.GetCurrentDirectory();
163+
try
164+
{
165+
Directory.SetCurrentDirectory(testDir.Root);
166+
var result = await CreateConfigCommand.RunAsync(FileSystemStorageType.Local, string.Empty, NullLogger.Instance);
167+
168+
result.Should().BeTrue();
169+
File.Exists(Path.Combine(testDir.Root, "sleet.json")).Should().BeTrue();
170+
}
171+
finally
172+
{
173+
Directory.SetCurrentDirectory(originalDir);
174+
}
175+
}
176+
}
177+
}
178+
}

0 commit comments

Comments
 (0)