diff --git a/MergerLogic/Clients/FileClient.cs b/MergerLogic/Clients/FileClient.cs index 25544910..858e4f6a 100644 --- a/MergerLogic/Clients/FileClient.cs +++ b/MergerLogic/Clients/FileClient.cs @@ -1,4 +1,6 @@ using MergerLogic.Batching; +using MergerLogic.ImageProcessing; +using System; using System.IO.Abstractions; using MergerLogic.Utils; @@ -36,16 +38,17 @@ public override bool TileExists(int z, int x, int y) private string? GetTilePath(int z, int x, int y) { - var tilePath = this._fileSystem.Path.Join(z.ToString(), x.ToString(), y.ToString()); - try + // Probe each supported extension via File.Exists (false for a missing dir too, so no glob/catch). + foreach (TileFormat format in Enum.GetValues()) { - //this may or may not be faster then checking specific files of every supported type depending on the used file system - return this._fileSystem.Directory - .EnumerateFiles(this.path, $"{tilePath}.*", SearchOption.TopDirectoryOnly).FirstOrDefault(); - } - catch (DirectoryNotFoundException) - { - return null; + string candidate = this._fileSystem.Path.Combine( + this.path, z.ToString(), x.ToString(), $"{y}.{format.ToString().ToLower()}"); + if (this._fileSystem.File.Exists(candidate)) + { + return candidate; + } } + + return null; } } diff --git a/MergerLogic/ImageProcessing/ImageFormatter.cs b/MergerLogic/ImageProcessing/ImageFormatter.cs index 50c75d95..8048d027 100644 --- a/MergerLogic/ImageProcessing/ImageFormatter.cs +++ b/MergerLogic/ImageProcessing/ImageFormatter.cs @@ -5,8 +5,8 @@ namespace MergerLogic.ImageProcessing { public enum TileFormat { - [EnumMember(Value = "png")] Png, [EnumMember(Value = "jpeg")] Jpeg, + [EnumMember(Value = "png")] Png, } public class TileFormatStrategy { diff --git a/MergerLogicUnitTests/Clients/FileClientTest.cs b/MergerLogicUnitTests/Clients/FileClientTest.cs index 1b9cd607..f991be52 100644 --- a/MergerLogicUnitTests/Clients/FileClientTest.cs +++ b/MergerLogicUnitTests/Clients/FileClientTest.cs @@ -68,25 +68,12 @@ public void GetTile(bool useCoords, bool returnsNull, TileFormat targetFormat) Coord cords = new Coord(1, 2, 3); byte[] data = targetFormat == TileFormat.Jpeg ? this._jpegImageData : this._pngImageData; - var seq = new MockSequence(); - this._pathMock - .InSequence(seq) - .Setup(util => util.Join(cords.Z.ToString(), cords.X.ToString(), cords.Y.ToString())) - .Returns("testTilePath"); - this._directoryMock - .InSequence(seq) - .Setup(dir => dir.EnumerateFiles("testFilePath", "testTilePath.*", SearchOption.TopDirectoryOnly)) - .Returns(returnsNull ? Array.Empty() : new string[] { "testTilePath" }); + SetupTilePathProbe(cords, returnsNull, targetFormat, out string? foundPath); if (!returnsNull) { this._fileMock - .InSequence(seq) - .Setup(util => util.ReadAllBytes("testTilePath")) + .Setup(util => util.ReadAllBytes(foundPath)) .Returns(data); - this._imageFormatterMock - .InSequence(seq) - .Setup(formatter => formatter.GetTileFormat(data)) - .Returns(targetFormat); } var fileClient = new FileClient("testFilePath", this._geoUtilsMock.Object, this._fsMock.Object); @@ -107,6 +94,31 @@ public void GetTile(bool useCoords, bool returnsNull, TileFormat targetFormat) this._repository.VerifyAll(); } + // GetTilePath probes jpeg then png via File.Exists. Sets up only the calls the probe actually + // makes: png is not probed once jpeg is found, so its setups are omitted (strict mocks). + private void SetupTilePathProbe(Coord cords, bool missing, TileFormat targetFormat, out string? foundPath) + { + string jpegPath = "1/2/3.jpeg"; + string pngPath = "1/2/3.png"; + bool jpegExists = !missing && targetFormat == TileFormat.Jpeg; + bool pngExists = !missing && targetFormat == TileFormat.Png; + + this._pathMock + .Setup(p => p.Combine("testFilePath", cords.Z.ToString(), cords.X.ToString(), $"{cords.Y}.jpeg")) + .Returns(jpegPath); + this._fileMock.Setup(f => f.Exists(jpegPath)).Returns(jpegExists); + + if (!jpegExists) + { + this._pathMock + .Setup(p => p.Combine("testFilePath", cords.Z.ToString(), cords.X.ToString(), $"{cords.Y}.png")) + .Returns(pngPath); + this._fileMock.Setup(f => f.Exists(pngPath)).Returns(pngExists); + } + + foundPath = jpegExists ? jpegPath : (pngExists ? pngPath : null); + } + #endregion #region TileExists @@ -117,17 +129,8 @@ public void GetTile(bool useCoords, bool returnsNull, TileFormat targetFormat) public void TileExists(bool exist) { Coord cords = new Coord(1, 2, 3); - byte[] data = this._jpegImageData; - var seq = new MockSequence(); - this._pathMock - .InSequence(seq) - .Setup(util => util.Join(cords.Z.ToString(), cords.X.ToString(), cords.Y.ToString())) - .Returns("testTilePath"); - this._directoryMock - .InSequence(seq) - .Setup(dir => dir.EnumerateFiles("testFilePath", "testTilePath.*", SearchOption.TopDirectoryOnly)) - .Returns(exist ? new string[] { "testFile" } : Array.Empty()); + SetupTilePathProbe(cords, !exist, TileFormat.Jpeg, out _); var fileClient = new FileClient("testFilePath", this._geoUtilsMock.Object, this._fsMock.Object); @@ -137,29 +140,6 @@ public void TileExists(bool exist) this._repository.VerifyAll(); } - [TestMethod] - public void TileExistsReturnFalseWhenDirectoryDontExist() - { - Coord cords = new Coord(1, 2, 3); - - var seq = new MockSequence(); - this._pathMock - .InSequence(seq) - .Setup(util => util.Join(cords.Z.ToString(), cords.X.ToString(), cords.Y.ToString())) - .Returns("testTilePath"); - this._directoryMock - .InSequence(seq) - .Setup(dir => dir.EnumerateFiles("testFilePath", "testTilePath.*", SearchOption.TopDirectoryOnly)) - .Throws(); - - var fileClient = new FileClient("testFilePath", this._geoUtilsMock.Object, this._fsMock.Object); - - var res = fileClient.TileExists(cords.Z, cords.X, cords.Y); - - Assert.AreEqual(false, res); - this._repository.VerifyAll(); - } - #endregion }