using System; using System.Threading.Tasks; using MonkeyCache.FileStore; using Newtonsoft.Json; using NSubstitute; using NSubstitute.ExceptionExtensions; using NUnit.Framework; using ShareeBike.Model.Services.CopriApi; using ShareeBike.Repository; using ShareeBike.Repository.Exception; using ShareeBike.Repository.Response; using ShareeBike.Repository.Response.Stations; using ShareeBike.Services.CopriApi; namespace SharedBusinessLogic.Tests.Fixtures.ObjectTests.Connector { [TestFixture] public class TestCopriProviderHttps { private const string BIKESAVAILABLE = @"{ ""copri_version"" : ""4.1.0.0"", ""bikes"" : {}, ""response_state"" : ""OK"", ""apiserver"" : ""https://app.tink-konstanz.de"", ""authcookie"" : """", ""response"" : ""bikes_available"", ""bikes"" : { ""2352"" : { ""description"" : ""Cargo Long"", ""state"" : ""available"", ""bike"" : ""1"", ""gps"" : { ""latitude"": ""47.669888"", ""longitude"": ""9.167749"" }, ""station"" : ""9"" } } }"; private const string BIKESOCCUPIED = @"{ ""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"", ""debuglevel"" : ""2"", ""user_group"" : [ ""ShareeBike"" ], ""user_id"" : ""javaminister@gmail.com"", ""response"" : ""user_bikes_occupied"", ""response_state"" : ""OK"", ""response_text"" : ""Die Liste der reservierten und gebuchten Fahrräder wurde erfolgreich geladen"", ""apiserver"" : ""https://tinkwwp.copri-bike.de"", ""bikes_occupied"" : { ""89004"" : { ""start_time"" : ""2018-01-27 17:33:00.989464+01"", ""station"" : ""9"", ""unit_price"" : ""2.00"", ""tariff_description"": { ""free_hours"" : ""0.5"", ""name"" : ""ShareeBike Tarif"", ""max_eur_per_day"" : ""9.00"" }, ""timeCode"" : ""2061"", ""description"" : ""Cargo Long"", ""bike"" : ""4"", ""total_price"" : ""20.00"", ""state"" : ""requested"", ""real_hours"" : ""66.05"", ""bike_group"" : [ ""ShareeBike"" ], ""now_time"" : ""2018-01-30 11:36:45"", ""request_time"" : ""2018-01-27 17:33:00.989464+01"", ""computed_hours"" : ""10.0"" } } }"; private const string STATIONSALL = @"{ ""copri_version"" : ""4.1.0.0"", ""stations"" : { ""5"" : { ""station"" : ""5"", ""bike_soll"" : ""0"", ""bike_ist"" : ""7"", ""station_group"" : [ ""ShareeBike"" ], ""gps"" : { ""latitude"": ""47.66756"", ""longitude"": ""9.16477"" }, ""state"" : ""available"", ""description"" : """" }, ""13"" : { ""station"" : ""13"", ""bike_soll"" : ""4"", ""bike_ist"" : ""1"", ""station_group"" : [ ""ShareeBike"" ], ""gps"" : { ""latitude"": ""47.657756"", ""longitude"": ""9.176084"" }, ""state"" : ""available"", ""description"" : """" }, ""30"" : { ""station"" : ""30"", ""bike_soll"" : ""5"", ""bike_ist"" : ""0"", ""station_group"" : [ ""ShareeBike"", ""Citybike"" ], ""gps"" : { ""latitude"": ""47.657766"", ""longitude"": ""9.176094"" }, ""state"" : ""available"", ""description"" : ""Test für Stadtradstation"" } }, ""bikes_occupied"" : {}, ""user_group"" : [ ""Citybike"", ""ShareeBike"" ], ""response_state"" : ""OK"", ""authcookie"" : ""6103_f782a208d9399291ba8d086b5dcc2509_12345678"", ""debuglevel"" : ""2"", ""response"" : ""stations_all"", ""user_id"" : ""javaminister@gmail.com"", ""apiserver"" : ""https://tinkwwp.copri-bike.de"" }"; [Test] public async Task TestGetBikesAvailable_NotExpired() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsBikesAvailableExpired.Returns(false); cache.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(BIKESAVAILABLE))); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123", // Merchant id new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), // User agent null /*UI language */, sessionCookie: "456", cacheServer: cache, httpsServer: https); var bikes = await provider.GetBikesAvailable(); Assert.That(bikes.Response.bikes.Count, Is.EqualTo(1)); Assert.That(bikes.Source.Name, Is.EqualTo(typeof(CopriCallsMonkeyStore).Name)); Assert.That(bikes.Exception, Is.Null); } [Test] public async Task TestGetBikesAvailable_ExpiredForceCache() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsBikesAvailableExpired.Returns(true); cache.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(BIKESAVAILABLE))); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123", new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), null /*UI language */, cacheServer: cache, httpsServer: https); var bikes = await provider.GetBikesAvailable(true); Assert.That(bikes.Response.bikes.Count, Is.EqualTo(1)); Assert.That(bikes.Source.Name, Is.EqualTo(typeof(CopriCallsMonkeyStore).Name)); Assert.That(bikes.Exception, Is.Null); } [Test] public async Task TestGetBikesAvailable_Expired() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsBikesAvailableExpired.Returns(true); https.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(BIKESAVAILABLE))); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123", new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), null /*UI language */, cacheServer: cache, httpsServer: https); var bikes = await provider.GetBikesAvailable(); Assert.That(bikes.Response.bikes.Count, Is.EqualTo(1)); Assert.That(bikes.Source.Name, Is.EqualTo(typeof(CopriCallsHttps).Name)); Assert.That(bikes.Exception, Is.Null); } [Test] public async Task TestGetBikesAvailable_Exception() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsBikesAvailableExpired.Returns(true); cache.GetBikesAvailableAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(BIKESAVAILABLE))); https.GetBikesAvailableAsync().Returns(x => { throw new WebConnectFailureException("Bang...", new System.Exception()); }); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123", new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), null /*UI language */, cacheServer: cache, httpsServer: https); var bikes = await provider.GetBikesAvailable(); Assert.That(bikes.Response.bikes.Count, Is.EqualTo(1)); Assert.That(bikes.Source.Name, Is.EqualTo(typeof(CopriCallsMonkeyStore).Name)); Assert.That(bikes.Exception.Message, Is.EqualTo("Bang...")); } [Test] public async Task TestGetBikesOccupied_NotExpired() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsBikesOccupiedExpired.Returns(false); cache.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(BIKESOCCUPIED))); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "12345678", // Merchant id new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), // User agent null /*UI language */, sessionCookie: "f782a208d9399291ba8d086b5dcc2509", cacheServer: cache, httpsServer: https); var bikes = await provider.GetBikesOccupied(); Assert.That(bikes.Response.bikes_occupied.Count, Is.EqualTo(1)); Assert.That(bikes.Source.Name, Is.EqualTo(typeof(CopriCallsMonkeyStore).Name)); Assert.That(bikes.Exception, Is.Null); } [Test] public async Task TestGetBikesOccupied_ExpiredForceCache() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsBikesOccupiedExpired.Returns(true); cache.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(BIKESOCCUPIED))); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "12345678", // Merchant id new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), // User agent null /*UI language */, sessionCookie: "f782a208d9399291ba8d086b5dcc2509", cacheServer: cache, httpsServer: https); var bikes = await provider.GetBikesOccupied(true); Assert.That(bikes.Response.bikes_occupied.Count, Is.EqualTo(1)); Assert.That(bikes.Source.Name, Is.EqualTo(typeof(CopriCallsMonkeyStore).Name)); Assert.That(bikes.Exception, Is.Null); } [Test] public async Task TestGetBikesOccupied_Expired() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsBikesOccupiedExpired.Returns(true); https.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(BIKESOCCUPIED))); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "12345678", // Merchant id new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), // User agent null /*UI language */, sessionCookie: "f782a208d9399291ba8d086b5dcc2509", cacheServer: cache, httpsServer: https); var bikes = await provider.GetBikesOccupied(); Assert.That(bikes.Response.bikes_occupied.Count, Is.EqualTo(1)); Assert.That(bikes.Source.Name, Is.EqualTo(typeof(CopriCallsHttps).Name)); Assert.That(bikes.Exception, Is.Null); } [Test] public async Task TestGetBikesOccupied_Exception() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsBikesOccupiedExpired.Returns(true); cache.GetBikesOccupiedAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(BIKESOCCUPIED))); https.GetBikesOccupiedAsync().Returns(x => { throw new WebConnectFailureException("Bang...", new System.Exception()); }); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "12345678", // Merchant id new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), // User agent null /*UI language */, sessionCookie: "f782a208d9399291ba8d086b5dcc2509", cacheServer: cache, httpsServer: https); var bikes = await provider.GetBikesOccupied(); Assert.That(bikes.Response.bikes_occupied.Count, Is.EqualTo(1)); Assert.That(bikes.Source.Name, Is.EqualTo(typeof(CopriCallsMonkeyStore).Name)); Assert.That(bikes.Exception.Message, Is.EqualTo("Bang...")); } [Test] public async Task TestGetStations_NotExpired() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsStationsExpired.Returns(false); cache.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(STATIONSALL))); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123", // Merchant id new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), // User agent null /*UI language */, sessionCookie: "456", // cookie cacheServer: cache, httpsServer: https); var stations = await provider.GetStations(); Assert.That(stations.Response.stations.Count, Is.EqualTo(3)); Assert.That(stations.Source.Name, Is.EqualTo(typeof(CopriCallsMonkeyStore).Name)); Assert.That(stations.Exception, Is.Null); } [Test] public async Task TestGetStations_ExpiredForceCache() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsStationsExpired.Returns(true); cache.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(STATIONSALL))); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123", new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), null /*UI language */, cacheServer: cache, httpsServer: https); var stations = await provider.GetStations(true); Assert.That(stations.Response.stations.Count, Is.EqualTo(3)); Assert.That(stations.Source.Name, Is.EqualTo(typeof(CopriCallsMonkeyStore).Name)); Assert.That(stations.Exception, Is.Null); } [Test] public async Task TestGetStations_Expired() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsStationsExpired.Returns(true); https.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(STATIONSALL))); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123", new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), null /*UI language */, cacheServer: cache, httpsServer: https); var stations = await provider.GetStations(); Assert.That(stations.Response.stations.Count, Is.EqualTo(3)); Assert.That(stations.Source.Name, Is.EqualTo(typeof(CopriCallsHttps).Name)); Assert.That(stations.Exception, Is.Null); } [Test] public async Task TestGetStations_Exception() { var cache = Substitute.For(); var https = Substitute.For(); cache.IsStationsExpired.Returns(true); cache.GetStationsAsync().Returns(Task.Run(() => JsonConvert.DeserializeObject(STATIONSALL))); https.GetStationsAsync().Returns(x => { throw new WebConnectFailureException("Bang...", new System.Exception()); }); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123", new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), null /*UI language */, cacheServer: cache, httpsServer: https); var stations = await provider.GetStations(); Assert.That(stations.Response.stations.Count, Is.EqualTo(3)); Assert.That(stations.Source.Name, Is.EqualTo(typeof(CopriCallsMonkeyStore).Name)); Assert.That(stations.Exception.Message, Is.EqualTo("Bang...")); } [Test] public async Task Test_AddToCache_Stations() { if (string.IsNullOrEmpty(Barrel.ApplicationId)) { Barrel.ApplicationId = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; } Barrel.Current.EmptyAll(); var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123456789", new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), null /*UI language */); var stations = await provider.GetStations(true); Assert.That(stations.Response.stations.Count, Is.EqualTo(0)); try { // Do not add if an exception occurred provider.AddToCache(new Result(typeof(CopriCallsHttps), JsonConvert.DeserializeObject(STATIONSALL), new GeneralData(), new System.Exception("Bang..."))); stations = await provider.GetStations(true); Assert.That(stations.Response.stations.Count, Is.EqualTo(0)); // Do not add if results from cache provider.AddToCache(new Result(typeof(CopriCallsMonkeyStore), JsonConvert.DeserializeObject(STATIONSALL), new GeneralData())); stations = await provider.GetStations(true); Assert.That(stations.Response.stations.Count, Is.EqualTo(0)); // Add result provider.AddToCache(new Result(typeof(CopriCallsHttps), JsonConvert.DeserializeObject(STATIONSALL), new GeneralData())); stations = await provider.GetStations(true); Assert.That(stations.Response.stations.Count, Is.EqualTo(3)); } finally { Barrel.Current.EmptyAll(); } } [Test] public void Test_AddToCache() { var cache = Substitute.For(); var provider = new CopriProviderHttps( new Uri("https://copri.net"), "MerchId", new AppContextInfo("MerchId", "Name", new Version()), "de-de", cacheServer: cache); var uri = new Uri("https://Myserver.com"); var station = "MyStation"; var bike = "MyBike"; var result = new Result(typeof(CopriCallsHttps), JsonConvert.DeserializeObject(BIKESAVAILABLE), new GeneralData()); provider.AddToCache(result, uri, station, bike); cache.Received().AddToCache(result.Response, uri, station, bike); } [Test] public async Task Test_AddToCache_BikesAvailable() { if (string.IsNullOrEmpty(Barrel.ApplicationId)) { Barrel.ApplicationId = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; } var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123456789", new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), null /*UI language */); var bikes = await provider.GetBikesAvailable(true); Assert.That(bikes.Response.bikes.Count, Is.EqualTo(0)); try { // Do not add if an exception occurred provider.AddToCache( new Result(typeof(CopriCallsHttps), JsonConvert.DeserializeObject(BIKESAVAILABLE), new GeneralData(), new System.Exception("Bang...")), stationId: "9"); bikes = await provider.GetBikesAvailable(true, stationId: "9"); Assert.That(bikes.Response.bikes.Count, Is.EqualTo(0)); // Do not add if results from cache provider.AddToCache(new Result( typeof(CopriCallsMonkeyStore), JsonConvert.DeserializeObject(BIKESAVAILABLE), new GeneralData()), stationId: "9"); bikes = await provider.GetBikesAvailable(true, stationId: "9"); Assert.That(bikes.Response.bikes.Count, Is.EqualTo(0)); // Add result provider.AddToCache( new Result(typeof(CopriCallsHttps), JsonConvert.DeserializeObject(BIKESAVAILABLE), new GeneralData()), stationId: "9"); bikes = await provider.GetBikesAvailable(true, stationId: "9"); Assert.That(bikes.Response.bikes.Count, Is.EqualTo(1)); } finally { Barrel.Current.EmptyAll(); } } [Test] public async Task Test_AddToCache_BikesOccupied() { if (string.IsNullOrEmpty(Barrel.ApplicationId)) { Barrel.ApplicationId = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name; } var provider = new CopriProviderHttps( new Uri("http://1.2.3.4"), "123456789", new AppContextInfo("oiF2kahH", "sharee.bike.test", new Version(3, 0, 267)), // User agent null /* language */, sessionCookie: "876"); var bikes = await provider.GetBikesOccupied(true); Assert.That(bikes.Response.bikes_occupied.Count, Is.EqualTo(0)); try { // Do not add if an exception occurred provider.AddToCache(new Result(typeof(CopriCallsHttps), JsonConvert.DeserializeObject(BIKESOCCUPIED), new GeneralData(), new System.Exception("Bang..."))); bikes = await provider.GetBikesOccupied(true); Assert.That(bikes.Response.bikes_occupied.Count, Is.EqualTo(0)); // Do not add if results from cache provider.AddToCache(new Result(typeof(CopriCallsMonkeyStore), JsonConvert.DeserializeObject(BIKESOCCUPIED), new GeneralData())); bikes = await provider.GetBikesOccupied(true); Assert.That(bikes.Response.bikes_occupied.Count, Is.EqualTo(0)); // Add result provider.AddToCache(new Result(typeof(CopriCallsHttps), JsonConvert.DeserializeObject(BIKESOCCUPIED), new GeneralData())); bikes = await provider.GetBikesOccupied(true); Assert.That(bikes.Response.bikes_occupied.Count, Is.EqualTo(1)); } finally { Barrel.Current.EmptyAll(); } } /// /// Verify that cache updating functionality is called correctly. /// [Test] public async Task TestDoReserveAsync() { var cache = Substitute.For(); var https = Substitute.For(); var provider = new CopriProviderHttps( new Uri("https://copri.net"), "MerchId", new AppContextInfo("MerchId", "Name", new Version()), "de-de", cacheServer: cache, httpsServer: https); var uri = new Uri("https://Myserver.com"); const string bikeId = "BikeNr12"; https.DoReserveAsync(bikeId, uri).Returns(Task.FromResult(JsonConvert.DeserializeObject(@" { bike : ""BikeNr12"", ""bikes_occupied"" : { ""BikeNr3"" : { ""bike"" : ""BikeNr3"", ""station"" : ""Freiburg City"" }, ""BikeNr12"" : { ""bike"" : ""BikeNr12"", ""station"" : ""HomeSweetHome"" } }, ""response_state"" : ""OK"" }"))); await provider.DoReserveAsync(bikeId, uri); cache.Received().Update(Arg.Is(x => x.station == "HomeSweetHome")); } /// /// Verify that cache updating functionality is not called in case of an exception being thrown. /// [Test] public void TestDoReserveAsyncException() { var cache = Substitute.For(); var https = Substitute.For(); var provider = new CopriProviderHttps( new Uri("https://copri.net"), "MerchId", new AppContextInfo("MerchId", "Name", new Version()), "de-de", cacheServer: cache, httpsServer: https); var uri = new Uri("https://Myserver.com"); const string bikeId = "BikeNr12"; https.DoReserveAsync(bikeId, uri).Throws(new System.Exception("Something went wrong...")); Assert.That(async() => await provider.DoReserveAsync(bikeId, uri), Throws.Exception); cache.DidNotReceive().Update(Arg.Any()); } /// /// Verify that cache updating functionality is called correctly. /// [Test] public async Task TestDoBookAsyncAsync() { var cache = Substitute.For(); var https = Substitute.For(); var provider = new CopriProviderHttps( new Uri("https://copri.net"), "MerchId", new AppContextInfo("MerchId", "Name", new Version()), "de-de", cacheServer: cache, httpsServer: https); var uri = new Uri("https://Myserver.com"); const string bikeId = "BikeNr12"; https.DoBookAsync(uri, bikeId, new Guid(), 0).Returns(Task.FromResult(JsonConvert.DeserializeObject(@" { bike : ""BikeNr12"", ""bikes_occupied"" : { ""BikeNr3"" : { ""bike"" : ""BikeNr3"", ""station"" : ""Freiburg City"" }, ""BikeNr12"" : { ""bike"" : ""BikeNr12"", ""station"" : ""HomeSweetHome"" } }, ""response_state"" : ""OK"" }"))); await provider.DoBookAsync(uri, bikeId, new Guid(), 0); cache.Received().Update(Arg.Is(x => x.station == "HomeSweetHome")); } /// /// Verify that cache updating functionality is not called in case of an exception being thrown. /// [Test] public void TestDoBookAsyncAsyncException() { var cache = Substitute.For(); var https = Substitute.For(); var provider = new CopriProviderHttps( new Uri("https://copri.net"), "MerchId", new AppContextInfo("MerchId", "Name", new Version()), "de-de", cacheServer: cache, httpsServer: https); var uri = new Uri("https://Myserver.com"); const string bikeId = "BikeNr12"; https.DoBookAsync(uri, bikeId, new Guid(), 0).Throws(new System.Exception("Something went wrong...")); Assert.That(async () => await provider.DoBookAsync(uri, bikeId, new Guid(), 0), Throws.Exception); cache.DidNotReceive().Update(Arg.Any()); } } }