public void TileFetcherWithFailingFetchesShouldTryAgain() { // Arrange var tileProvider = new FailingTileProvider(); var tileSchema = new GlobalSphericalMercator(); var tileSource = new TileSource(tileProvider, tileSchema); var cache = new MemoryCache <Feature>(); var fetchDispatcher = new TileFetchDispatcher(cache, tileSource.Schema, (tileInfo) => TileToFeature(tileSource, tileInfo)); var tileMachine = new FetchMachine(fetchDispatcher); var level = "3"; var tilesInLevel = 64; // Act fetchDispatcher.SetViewport(tileSchema.Extent.ToBoundingBox(), tileSchema.Resolutions[level].UnitsPerPixel); tileMachine.Start(); while (fetchDispatcher.Busy) { } // do it again fetchDispatcher.SetViewport(tileSchema.Extent.ToBoundingBox(), tileSchema.Resolutions[level].UnitsPerPixel); tileMachine.Start(); while (fetchDispatcher.Busy) { } // Assert Assert.AreEqual(tilesInLevel * 2, tileProvider.TotalCount); // tried all tiles twice }
public void TileFetcherShouldRequestAllTilesJustOnes() { // Arrange var tileProvider = new CountingTileProvider(); var tileSchema = new GlobalSphericalMercator(); var tileSource = new TileSource(tileProvider, tileSchema); var cache = new MemoryCache <Feature>(); var fetchDispatcher = new TileFetchDispatcher(cache, tileSource.Schema, (tileInfo) => TileToFeature(tileSource, tileInfo)); var tileMachine = new FetchMachine(fetchDispatcher); var level = "4"; var expextedTiles = 256; // Act // Get all tiles of level 3 fetchDispatcher.SetViewport(tileSchema.Extent.ToBoundingBox(), tileSchema.Resolutions[level].UnitsPerPixel); tileMachine.Start(); // Assert while (fetchDispatcher.Busy) { } Assert.AreEqual(expextedTiles, tileProvider.CountByTile.Keys.Count); Assert.AreEqual(expextedTiles, tileProvider.CountByTile.Values.Sum()); Assert.AreEqual(expextedTiles, tileProvider.TotalCount); }
public void TileRequestThatReturnsNullShouldNotBeRequestedAgain() { // Arrange var tileProvider = new NullTileProvider(); var tileSchema = new GlobalSphericalMercator(); var tileSource = new TileSource(tileProvider, tileSchema); var cache = new MemoryCache <Feature>(); var fetchDispatcher = new TileFetchDispatcher(cache, tileSource.Schema, (tileInfo) => TileToFeature(tileSource, tileInfo)); var tileMachine = new FetchMachine(fetchDispatcher); var level = "3"; var tilesInLevel = 64; // Act fetchDispatcher.SetViewport(tileSchema.Extent.ToBoundingBox(), tileSchema.Resolutions[level].UnitsPerPixel); tileMachine.Start(); while (fetchDispatcher.Busy) { } // do it again fetchDispatcher.SetViewport(tileSchema.Extent.ToBoundingBox(), tileSchema.Resolutions[level].UnitsPerPixel); tileMachine.Start(); while (fetchDispatcher.Busy) { Thread.Sleep(1); } // Assert Assert.AreEqual(tilesInLevel, tileProvider.TotalCount); }
public void TileFetcherShouldRequestAllTilesJustOnes() { // Arrange var tileProvider = new CountingTileProvider(); var tileSchema = new GlobalSphericalMercator(); var tileSource = new TileSource(tileProvider, tileSchema); using var cache = new MemoryCache <IFeature?>(); var fetchDispatcher = new TileFetchDispatcher(cache, tileSource.Schema, async tileInfo => await TileToFeatureAsync(tileSource, tileInfo)); var tileMachine = new FetchMachine(fetchDispatcher); var level = 3; var expectedTiles = 64; var fetchInfo = new FetchInfo(tileSchema.Extent.ToMRect(), tileSchema.Resolutions[level].UnitsPerPixel); // Act // Get all tiles of level 3 fetchDispatcher.SetViewport(fetchInfo); tileMachine.Start(); // Assert while (fetchDispatcher.Busy) { Thread.Sleep(1); } Assert.AreEqual(expectedTiles, tileProvider.CountByTile.Keys.Count); Assert.AreEqual(expectedTiles, tileProvider.CountByTile.Values.Sum()); Assert.AreEqual(expectedTiles, tileProvider.TotalCount); }
public void RepeatedRestartsShouldNotCauseInfiniteLoop() { // Arrange var tileProvider = new CountingTileProvider(); var tileSchema = new GlobalSphericalMercator(); var tileSource = new TileSource(tileProvider, tileSchema); var cache = new MemoryCache <Feature>(); var fetchDispatcher = new TileFetchDispatcher(cache, tileSource.Schema, (tileInfo) => TileToFeature(tileSource, tileInfo)); var tileMachine = new FetchMachine(fetchDispatcher); var numberOfWorkers = 8; var numberOfRestarts = 3; // Act for (int i = 0; i < numberOfRestarts; i++) { fetchDispatcher.SetViewport(tileSchema.Extent.ToBoundingBox(), tileSchema.Resolutions["3"].UnitsPerPixel); tileMachine.Start(); while (fetchDispatcher.Busy) { } } // Assert Assert.Greater(numberOfWorkers * numberOfRestarts, FetchWorker.RestartCounter); }
/// <summary> /// Create tile layer for given tile source /// </summary> /// <param name="source">Tile source to use for this layer</param> /// <param name="minTiles">Minimum number of tiles to cache</param> /// <param name="maxTiles">Maximum number of tiles to cache</param> /// <param name="maxRetries">Unused</param> /// <param name="dataFetchStrategy">Strategy to get list of tiles for given extent</param> /// <param name="renderFetchStrategy"></param> /// <param name="minExtraTiles">Number of minimum extra tiles for memory cache</param> /// <param name="maxExtraTiles">Number of maximum extra tiles for memory cache</param> // ReSharper disable once UnusedParameter.Local // Is public and won't break this now public TileLayer(ITileSource source = null, int minTiles = 200, int maxTiles = 300, IDataFetchStrategy dataFetchStrategy = null, IRenderFetchStrategy renderFetchStrategy = null, int minExtraTiles = -1, int maxExtraTiles = -1, Func <TileInfo, Feature> fetchTileAsFeature = null) { MemoryCache = new MemoryCache <Feature>(minTiles, maxTiles); Style = new VectorStyle { Outline = { Color = Color.FromArgb(0, 0, 0, 0) } }; // initialize with transparent outline _tileSource = source; if (_tileSource != null) { if (Attribution == null) { Attribution = new Hyperlink(); } Attribution.Text = _tileSource.Attribution?.Text; Attribution.Url = _tileSource.Attribution?.Url; } _envelope = _tileSource?.Schema?.Extent.ToBoundingBox(); dataFetchStrategy = dataFetchStrategy ?? new DataFetchStrategy(3); _renderFetchStrategy = renderFetchStrategy ?? new RenderFetchStrategy(); _minExtraTiles = minExtraTiles; _maxExtraTiles = maxExtraTiles; _tileFetchDispatcher = new TileFetchDispatcher(MemoryCache, source.Schema, fetchTileAsFeature ?? ToFeature, dataFetchStrategy); _tileFetchDispatcher.DataChanged += TileFetchDispatcherOnDataChanged; _tileFetchDispatcher.PropertyChanged += TileFetchDispatcherOnPropertyChanged; }
public void RepeatedRestartsShouldNotCauseInfiniteLoop() { // Arrange var tileProvider = new CountingTileProvider(); var tileSchema = new GlobalSphericalMercator(); var tileSource = new TileSource(tileProvider, tileSchema); using var cache = new MemoryCache <IFeature?>(); var fetchDispatcher = new TileFetchDispatcher(cache, tileSource.Schema, async tileInfo => await TileToFeatureAsync(tileSource, tileInfo)); var tileMachine = new FetchMachine(fetchDispatcher); var numberOfWorkers = 8; var numberOfRestarts = 3; var fetchInfo = new FetchInfo(tileSchema.Extent.ToMRect(), tileSchema.Resolutions[3].UnitsPerPixel); // Act for (var i = 0; i < numberOfRestarts; i++) { fetchDispatcher.SetViewport(fetchInfo); tileMachine.Start(); while (fetchDispatcher.Busy) { Thread.Sleep(1); } } // Assert Assert.Greater(numberOfWorkers * numberOfRestarts, FetchWorker.RestartCounter); }
public void TileFetcherWithFailingFetchesShouldTryAgain() { // Arrange var tileProvider = new FailingTileProvider(); var tileSchema = new GlobalSphericalMercator(); var tileSource = new TileSource(tileProvider, tileSchema); using var cache = new MemoryCache <IFeature?>(); var fetchDispatcher = new TileFetchDispatcher(cache, tileSource.Schema, async tileInfo => await TileToFeatureAsync(tileSource, tileInfo)); var tileMachine = new FetchMachine(fetchDispatcher); var level = 3; var tilesInLevel = 64; var fetchInfo = new FetchInfo(tileSchema.Extent.ToMRect(), tileSchema.Resolutions[level].UnitsPerPixel); // Act fetchDispatcher.SetViewport(fetchInfo); tileMachine.Start(); while (fetchDispatcher.Busy) { Thread.Sleep(1); } // Act again fetchDispatcher.SetViewport(fetchInfo); tileMachine.Start(); while (fetchDispatcher.Busy) { Thread.Sleep(1); } // Assert Assert.AreEqual(tilesInLevel * 2, tileProvider.TotalCount); // tried all tiles twice }
/// <summary> /// Create tile layer for given tile source /// </summary> /// <param name="source">Tile source to use for this layer</param> /// <param name="minTiles">Minimum number of tiles to cache</param> /// <param name="maxTiles">Maximum number of tiles to cache</param> /// <param name="maxRetries">Unused</param> /// <param name="fetchStrategy">Strategy to get list of tiles for given extent</param> /// <param name="renderFetchStrategy"></param> /// <param name="minExtraTiles">Number of minimum extra tiles for memory cache</param> /// <param name="maxExtraTiles">Number of maximum extra tiles for memory cache</param> // ReSharper disable once UnusedParameter.Local // Is public and won't break this now public TileLayer(ITileSource source = null, int minTiles = 200, int maxTiles = 300, int maxRetries = 2, IFetchStrategy fetchStrategy = null, IRenderGetStrategy renderFetchStrategy = null, int minExtraTiles = -1, int maxExtraTiles = -1) { MemoryCache = new MemoryCache<Feature>(minTiles, maxTiles); Style = new VectorStyle { Outline = { Color = Color.FromArgb(0, 0, 0, 0) } }; // initialize with transparent outline var fetchStrategy1 = fetchStrategy ?? new FetchStrategy(3); _renderStrategy = renderFetchStrategy ?? new RenderGetStrategy(); _minExtraTiles = minExtraTiles; _maxExtraTiles = maxExtraTiles; _tileFetchDispatcher = new TileFetchDispatcher(MemoryCache, fetchStrategy1); _tileFetchDispatcher.DataChanged += TileFetchDispatcherOnDataChanged; _tileFetchDispatcher.PropertyChanged += TileFetchDispatcherOnPropertyChanged; _fetchMachine = new FetchMachine(_tileFetchDispatcher); SetTileSource(source); }
/// <summary> /// Create tile layer for given tile source /// </summary> /// <param name="tileSource">Tile source to use for this layer</param> /// <param name="minTiles">Minimum number of tiles to cache</param> /// <param name="maxTiles">Maximum number of tiles to cache</param> /// <param name="dataFetchStrategy">Strategy to get list of tiles for given extent</param> /// <param name="renderFetchStrategy"></param> /// <param name="minExtraTiles">Number of minimum extra tiles for memory cache</param> /// <param name="maxExtraTiles">Number of maximum extra tiles for memory cache</param> /// <param name="fetchTileAsFeature">Fetch tile as feature</param> // ReSharper disable once UnusedParameter.Local // Is public and won't break this now public TileLayer(ITileSource tileSource, int minTiles = 200, int maxTiles = 300, IDataFetchStrategy?dataFetchStrategy = null, IRenderFetchStrategy?renderFetchStrategy = null, int minExtraTiles = -1, int maxExtraTiles = -1, Func <TileInfo, Task <IFeature?> >?fetchTileAsFeature = null) { _tileSource = tileSource ?? throw new ArgumentException($"{tileSource} can not null"); MemoryCache = new MemoryCache <IFeature?>(minTiles, maxTiles); Style = new RasterStyle(); Attribution.Text = _tileSource.Attribution?.Text; Attribution.Url = _tileSource.Attribution?.Url; _extent = _tileSource.Schema?.Extent.ToMRect(); dataFetchStrategy ??= new DataFetchStrategy(3); _renderFetchStrategy = renderFetchStrategy ?? new RenderFetchStrategy(); _minExtraTiles = minExtraTiles; _maxExtraTiles = maxExtraTiles; _tileFetchDispatcher = new TileFetchDispatcher(MemoryCache, _tileSource.Schema, fetchTileAsFeature ?? ToFeatureAsync, dataFetchStrategy); _tileFetchDispatcher.DataChanged += TileFetchDispatcherOnDataChanged; _tileFetchDispatcher.PropertyChanged += TileFetchDispatcherOnPropertyChanged; }
/// <summary> /// Create tile layer for given tile source /// </summary> /// <param name="source">Tile source to use for this layer</param> /// <param name="minTiles">Minimum number of tiles to cache</param> /// <param name="maxTiles">Maximum number of tiles to cache</param> /// <param name="maxRetries">Unused</param> /// <param name="fetchStrategy">Strategy to get list of tiles for given extent</param> /// <param name="renderGetStrategy"></param> /// <param name="minExtraTiles">Number of minimum extra tiles for memory cache</param> /// <param name="maxExtraTiles">Number of maximum extra tiles for memory cache</param> // ReSharper disable once UnusedParameter.Local // Is public and won't break this now public TileLayer(ITileSource source = null, int minTiles = 200, int maxTiles = 300, IFetchStrategy fetchStrategy = null, IRenderGetStrategy renderGetStrategy = null, int minExtraTiles = -1, int maxExtraTiles = -1, Func <TileInfo, Feature> fetchTileAsFeature = null) { MemoryCache = new MemoryCache <Feature>(minTiles, maxTiles); Style = new VectorStyle { Outline = { Color = Color.FromArgb(0, 0, 0, 0) } }; // initialize with transparent outline _tileSource = source; _envelope = _tileSource?.Schema?.Extent.ToBoundingBox(); fetchStrategy = fetchStrategy ?? new FetchStrategy(3); _renderGetStrategy = renderGetStrategy ?? new RenderGetStrategy(); _minExtraTiles = minExtraTiles; _maxExtraTiles = maxExtraTiles; _tileFetchDispatcher = new TileFetchDispatcher(MemoryCache, source.Schema, fetchTileAsFeature ?? ToFeature, fetchStrategy); _tileFetchDispatcher.DataChanged += TileFetchDispatcherOnDataChanged; _tileFetchDispatcher.PropertyChanged += TileFetchDispatcherOnPropertyChanged; }
/// <summary> /// Create tile layer for given tile source /// </summary> /// <param name="tileSource">Tile source to use for this layer</param> /// <param name="minTiles">Minimum number of tiles to cache</param> /// <param name="maxTiles">Maximum number of tiles to cache</param> /// <param name="dataFetchStrategy">Strategy to get list of tiles for given extent</param> /// <param name="renderFetchStrategy"></param> /// <param name="minExtraTiles">Number of minimum extra tiles for memory cache</param> /// <param name="maxExtraTiles">Number of maximum extra tiles for memory cache</param> /// <param name="fetchTileAsFeature">Fetch tile as feature</param> // ReSharper disable once UnusedParameter.Local // Is public and won't break this now public TileLayer(ITileSource tileSource, int minTiles = 200, int maxTiles = 300, IDataFetchStrategy?dataFetchStrategy = null, IRenderFetchStrategy?renderFetchStrategy = null, int minExtraTiles = -1, int maxExtraTiles = -1, Func <TileInfo, IFeature?>?fetchTileAsFeature = null) { _tileSource = tileSource ?? throw new ArgumentException($"{tileSource} can not null"); MemoryCache = new MemoryCache <IFeature?>(minTiles, maxTiles); Style = new VectorStyle { Outline = { Color = Color.FromArgb(0, 0, 0, 0) } }; // initialize with transparent outline Attribution.Text = _tileSource.Attribution?.Text; Attribution.Url = _tileSource.Attribution?.Url; _extent = _tileSource.Schema?.Extent.ToMRect(); dataFetchStrategy ??= new DataFetchStrategy(3); _renderFetchStrategy = renderFetchStrategy ?? new RenderFetchStrategy(); _minExtraTiles = minExtraTiles; _maxExtraTiles = maxExtraTiles; _tileFetchDispatcher = new TileFetchDispatcher(MemoryCache, _tileSource.Schema, fetchTileAsFeature ?? ToFeature, dataFetchStrategy); _tileFetchDispatcher.DataChanged += TileFetchDispatcherOnDataChanged; _tileFetchDispatcher.PropertyChanged += TileFetchDispatcherOnPropertyChanged; }
public void TilesFetchedShouldNotBeFetchAgain() { // Arrange var tileProvider = new CountingTileProvider(); var tileSchema = new GlobalSphericalMercator(); var tileSource = new TileSource(tileProvider, tileSchema); using var cache = new MemoryCache <IFeature?>(); var fetchDispatcher = new TileFetchDispatcher(cache, tileSource.Schema, tileInfo => TileToFeature(tileSource, tileInfo)); var tileMachine = new FetchMachine(fetchDispatcher); var level = 3; var expectedTiles = 64; var fetchInfo = new FetchInfo(tileSchema.Extent.ToMRect(), tileSchema.Resolutions[level].UnitsPerPixel); // Act fetchDispatcher.SetViewport(fetchInfo); tileMachine.Start(); while (fetchDispatcher.Busy) { Thread.Sleep(1); } var countAfterFirstTry = tileProvider.CountByTile.Keys.Count; // do it again fetchDispatcher.SetViewport(fetchInfo); tileMachine.Start(); while (fetchDispatcher.Busy) { Thread.Sleep(1); } // Assert Assert.AreEqual(countAfterFirstTry, tileProvider.CountByTile.Values.Sum()); Assert.AreEqual(expectedTiles, tileProvider.CountByTile.Keys.Count); Assert.AreEqual(expectedTiles, tileProvider.CountByTile.Values.Sum()); Assert.AreEqual(expectedTiles, tileProvider.TotalCount); }
public void TileFetcherWithSometimesFailingFetchesShouldTryAgain() { // Arrange var tileProvider = new SometimesFailingTileProvider(); var tileSchema = new GlobalSphericalMercator(); var tileSource = new TileSource(tileProvider, tileSchema); using var cache = new MemoryCache <IFeature?>(); var fetchDispatcher = new TileFetchDispatcher(cache, tileSource.Schema, tileInfo => TileToFeature(tileSource, tileInfo)); var tileMachine = new FetchMachine(fetchDispatcher); var level = 3; var tilesInLevel = 64; var fetchInfo = new FetchInfo(tileSchema.Extent.ToMRect(), tileSchema.Resolutions[level].UnitsPerPixel); // Act fetchDispatcher.SetViewport(fetchInfo); tileMachine.Start(); while (fetchDispatcher.Busy) { Thread.Sleep(1); } var tileCountAfterFirstBatch = tileProvider.TotalCount; // Act again fetchDispatcher.SetViewport(fetchInfo); tileMachine.Start(); while (fetchDispatcher.Busy) { Thread.Sleep(1); } // Assert Assert.GreaterOrEqual(tileProvider.TotalCount, tileCountAfterFirstBatch); Assert.GreaterOrEqual(tileProvider.CountByTile.Values.Sum(), tilesInLevel); }