From 6f1820fec1bd2c31d717db929caf503597f11ff5 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Mon, 15 May 2017 14:40:22 +0300 Subject: [PATCH 01/90] Move PCL projects to .NET Standard --- .../Contoso.Forms.Demo.csproj | 4 +--- .../Contoso.Forms.Demo/project.json | 7 +++++-- .../Contoso.Forms.Puppet.csproj | 17 ++--------------- .../Contoso.Forms.Puppet/packages.config | 4 ---- .../Contoso.Forms.Puppet/project.json | 11 +++++++++++ .../Microsoft.Azure.Mobile.csproj | 6 ++++-- .../Microsoft.Azure.Mobile/project.json | 8 ++++++++ .../Microsoft.Azure.Mobile.Analytics.csproj | 6 ++++-- .../project.json | 8 ++++++++ .../Microsoft.Azure.Mobile.Crashes.csproj | 6 ++++-- .../Microsoft.Azure.Mobile.Crashes/project.json | 8 ++++++++ .../Microsoft.Azure.Mobile.Distribute.csproj | 6 ++++-- .../project.json | 8 ++++++++ .../Microsoft.Azure.Mobile.Push.csproj | 7 ++++--- .../Microsoft.Azure.Mobile.Push/project.json | 8 ++++++++ 15 files changed, 79 insertions(+), 35 deletions(-) delete mode 100644 Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/packages.config create mode 100644 Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/project.json create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile/project.json create mode 100644 SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics/project.json create mode 100644 SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes/project.json create mode 100644 SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute/project.json create mode 100644 SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push/project.json diff --git a/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/Contoso.Forms.Demo.csproj b/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/Contoso.Forms.Demo.csproj index 8c993f408..9ded68b0f 100644 --- a/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/Contoso.Forms.Demo.csproj +++ b/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/Contoso.Forms.Demo.csproj @@ -5,12 +5,10 @@ AnyCPU {8E7B51FC-8A9B-49F7-A40D-4D12BBF893B6} {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - true Library Contoso.Forms.Demo Contoso.Forms.Demo - v4.5 - Profile259 + v5.0 true diff --git a/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/project.json b/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/project.json index fb08eab62..619757397 100644 --- a/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/project.json +++ b/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/project.json @@ -4,9 +4,12 @@ "Microsoft.Azure.Mobile.Crashes": "0.11.1", "Microsoft.Azure.Mobile.Distribute": "0.11.1", "Microsoft.Azure.Mobile.Push": "0.11.1", - "Xamarin.Forms": "2.3.4.231" + "Xamarin.Forms": "2.3.4.231", + "NETStandard.Library": "1.6.0" }, "frameworks": { - ".NETPortable,Version=v4.5,Profile=Profile259": {} + "netstandard1.0": { + "imports": "portable-net45+win8+wpa81" + } } } \ No newline at end of file diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Contoso.Forms.Puppet.csproj b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Contoso.Forms.Puppet.csproj index 6cde254e8..29a4bddda 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Contoso.Forms.Puppet.csproj +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Contoso.Forms.Puppet.csproj @@ -5,12 +5,10 @@ AnyCPU {92313C69-3BC4-4276-A1C8-100C86183F12} {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - true Library Contoso.Forms.Puppet Contoso.Forms.Puppet - v4.5 - Profile259 + v5.0 @@ -95,18 +93,7 @@ - - ..\..\..\packages\Xamarin.Forms.2.3.4.231\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Core.dll - - - ..\..\..\packages\Xamarin.Forms.2.3.4.231\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Platform.dll - - - ..\..\..\packages\Xamarin.Forms.2.3.4.231\lib\portable-win+net45+wp80+win81+wpa81+MonoAndroid10+Xamarin.iOS10+xamarinmac20\Xamarin.Forms.Xaml.dll - - - - + diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/packages.config b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/packages.config deleted file mode 100644 index 33c48456f..000000000 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/project.json b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/project.json new file mode 100644 index 000000000..d398f6808 --- /dev/null +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/project.json @@ -0,0 +1,11 @@ +{ + "dependencies": { + "Xamarin.Forms": "2.3.4.231", + "NETStandard.Library": "1.6.0" + }, + "frameworks": { + "netstandard1.0": { + "imports": "portable-net45+win8+wpa81" + } + } +} \ No newline at end of file diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile/Microsoft.Azure.Mobile.csproj b/SDK/MobileCenter/Microsoft.Azure.Mobile/Microsoft.Azure.Mobile.csproj index 4f6c4d59d..0cb376176 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile/Microsoft.Azure.Mobile.csproj +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile/Microsoft.Azure.Mobile.csproj @@ -14,8 +14,7 @@ en-US 512 {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - Profile259 - v4.5 + v5.0 false none @@ -53,6 +52,9 @@ + + + - + + - - + + - - + + diff --git a/nuget/MacMobileCenterAnalytics.nuspec b/nuget/MacMobileCenterAnalytics.nuspec index 43ba547f3..a38ef489f 100644 --- a/nuget/MacMobileCenterAnalytics.nuspec +++ b/nuget/MacMobileCenterAnalytics.nuspec @@ -17,16 +17,16 @@ - - + + - - + + - - + + diff --git a/nuget/MacMobileCenterCrashes.nuspec b/nuget/MacMobileCenterCrashes.nuspec index 799cb9ae0..59fc2ca73 100644 --- a/nuget/MacMobileCenterCrashes.nuspec +++ b/nuget/MacMobileCenterCrashes.nuspec @@ -17,16 +17,16 @@ - - + + - - + + - - + + diff --git a/nuget/MacMobileCenterDistribute.nuspec b/nuget/MacMobileCenterDistribute.nuspec index f2b530315..05d48abc4 100644 --- a/nuget/MacMobileCenterDistribute.nuspec +++ b/nuget/MacMobileCenterDistribute.nuspec @@ -17,16 +17,16 @@ - - + + - - + + - - + + diff --git a/nuget/MacMobileCenterPush.nuspec b/nuget/MacMobileCenterPush.nuspec index 53440983e..010a3b06e 100644 --- a/nuget/MacMobileCenterPush.nuspec +++ b/nuget/MacMobileCenterPush.nuspec @@ -12,10 +12,7 @@ https://aka.ms/vbgfx2 https://aka.ms/p2wifj - - - - + @@ -28,16 +25,16 @@ - - + + - - + + - - + + diff --git a/nuget/MobileCenter.nuspec b/nuget/MobileCenter.nuspec index 040f22428..bde8675d3 100644 --- a/nuget/MobileCenter.nuspec +++ b/nuget/MobileCenter.nuspec @@ -12,6 +12,9 @@ https://aka.ms/vbgfx2 https://aka.ms/p2wifj + + + @@ -22,8 +25,9 @@ - - + + + diff --git a/nuget/MobileCenterAnalytics.nuspec b/nuget/MobileCenterAnalytics.nuspec index d82055a10..95776da61 100644 --- a/nuget/MobileCenterAnalytics.nuspec +++ b/nuget/MobileCenterAnalytics.nuspec @@ -18,8 +18,8 @@ - - + + diff --git a/nuget/MobileCenterCrashes.nuspec b/nuget/MobileCenterCrashes.nuspec index 8dc5abc1f..3b162145d 100644 --- a/nuget/MobileCenterCrashes.nuspec +++ b/nuget/MobileCenterCrashes.nuspec @@ -18,8 +18,8 @@ - - + + diff --git a/nuget/MobileCenterDistribute.nuspec b/nuget/MobileCenterDistribute.nuspec index b46a98a84..7c1c80b0b 100644 --- a/nuget/MobileCenterDistribute.nuspec +++ b/nuget/MobileCenterDistribute.nuspec @@ -18,8 +18,8 @@ - - + + diff --git a/nuget/MobileCenterPush.nuspec b/nuget/MobileCenterPush.nuspec index 7099e073e..925c91f64 100644 --- a/nuget/MobileCenterPush.nuspec +++ b/nuget/MobileCenterPush.nuspec @@ -12,10 +12,7 @@ https://aka.ms/vbgfx2 https://aka.ms/p2wifj - - - - + @@ -23,16 +20,13 @@ - - - $version$ - - + + diff --git a/nuget/WindowsMobileCenter.nuspec b/nuget/WindowsMobileCenter.nuspec index 148156728..000280529 100644 --- a/nuget/WindowsMobileCenter.nuspec +++ b/nuget/WindowsMobileCenter.nuspec @@ -20,6 +20,6 @@ - + diff --git a/nuget/WindowsMobileCenterAnalytics.nuspec b/nuget/WindowsMobileCenterAnalytics.nuspec index 86dfdf8ca..dae448d63 100644 --- a/nuget/WindowsMobileCenterAnalytics.nuspec +++ b/nuget/WindowsMobileCenterAnalytics.nuspec @@ -16,6 +16,6 @@ - + diff --git a/nuget/WindowsMobileCenterCrashes.nuspec b/nuget/WindowsMobileCenterCrashes.nuspec index 1436f0105..ecc936208 100644 --- a/nuget/WindowsMobileCenterCrashes.nuspec +++ b/nuget/WindowsMobileCenterCrashes.nuspec @@ -19,23 +19,23 @@ - - + + - - - + + + - - - + + + - - - + + + diff --git a/nuget/WindowsMobileCenterPush.nuspec b/nuget/WindowsMobileCenterPush.nuspec index 9280fff40..49918b06d 100644 --- a/nuget/WindowsMobileCenterPush.nuspec +++ b/nuget/WindowsMobileCenterPush.nuspec @@ -16,6 +16,6 @@ - + From a9953aee567615f4c5a6e38fd7565d64c274120d Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Mon, 15 May 2017 17:48:26 +0300 Subject: [PATCH 03/90] Revert usage msbuild in demo --- .../Contoso.Forms.Demo/Contoso.Forms.Demo.csproj | 1 + .../Contoso.Forms.Puppet/Contoso.Forms.Puppet.csproj | 1 + 2 files changed, 2 insertions(+) diff --git a/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/Contoso.Forms.Demo.csproj b/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/Contoso.Forms.Demo.csproj index 9ded68b0f..6cc9a18c1 100644 --- a/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/Contoso.Forms.Demo.csproj +++ b/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo/Contoso.Forms.Demo.csproj @@ -5,6 +5,7 @@ AnyCPU {8E7B51FC-8A9B-49F7-A40D-4D12BBF893B6} {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true Library Contoso.Forms.Demo Contoso.Forms.Demo diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Contoso.Forms.Puppet.csproj b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Contoso.Forms.Puppet.csproj index 29a4bddda..f1fd1febb 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Contoso.Forms.Puppet.csproj +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Contoso.Forms.Puppet.csproj @@ -5,6 +5,7 @@ AnyCPU {92313C69-3BC4-4276-A1C8-100C86183F12} {786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + true Library Contoso.Forms.Puppet Contoso.Forms.Puppet From 08aabfbe7d2d3f571726e7285b54267cbabfdcfb Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 18 May 2017 18:40:36 -0700 Subject: [PATCH 04/90] Make httpclient lazy to avoid blocking in ui thread --- .../Ingestion/Http/HttpNetworkAdapter.cs | 43 ++++++++++++++++--- .../Ingestion/Http/IHttpNetworkAdapter.cs | 2 - .../Ingestion/Http/IngestionHttp.cs | 5 +-- 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/HttpNetworkAdapter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/HttpNetworkAdapter.cs index 5c16a6815..66b27c0a0 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/HttpNetworkAdapter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/HttpNetworkAdapter.cs @@ -7,11 +7,35 @@ namespace Microsoft.Azure.Mobile.Ingestion.Http { public sealed class HttpNetworkAdapter : IHttpNetworkAdapter { - private readonly HttpClient _httpClient = new HttpClient(); - public TimeSpan Timeout + private HttpClient _httpClient; + private TimeSpan? _timeout; + private object _lockObject = new object(); + + public HttpNetworkAdapter(TimeSpan? timeout = null) { - get { return _httpClient.Timeout; } - set { _httpClient.Timeout = value; } + _timeout = timeout; + } + + private HttpClient HttpClient + { + get + { + lock (_lockObject) + { + if (_httpClient != null) + { + return _httpClient; + } + + _httpClient = new HttpClient(); + + if (_timeout.HasValue) + { + _httpClient.Timeout = _timeout.Value; + } + return _httpClient; + } + } } /// @@ -19,7 +43,7 @@ public async Task SendAsync(HttpRequestMessage request, Can { try { - return await _httpClient.SendAsync(request, cancellationToken).ConfigureAwait(false); + return await HttpClient.SendAsync(request, cancellationToken).ConfigureAwait(false); } catch (InvalidOperationException e) { @@ -33,7 +57,14 @@ public async Task SendAsync(HttpRequestMessage request, Can public void Dispose() { - _httpClient.Dispose(); + lock (_lockObject) + { + if (_httpClient != null) + { + _httpClient.Dispose(); + _httpClient = null; + } + } } } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IHttpNetworkAdapter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IHttpNetworkAdapter.cs index 291d86c8d..068cbd625 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IHttpNetworkAdapter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IHttpNetworkAdapter.cs @@ -7,8 +7,6 @@ namespace Microsoft.Azure.Mobile.Ingestion.Http { public interface IHttpNetworkAdapter : IDisposable { - TimeSpan Timeout { get; set; } - Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken); } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IngestionHttp.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IngestionHttp.cs index 4718753b8..18a1e2a11 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IngestionHttp.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IngestionHttp.cs @@ -17,19 +17,18 @@ public sealed class IngestionHttp : IIngestion internal const string AppSecret = "App-Secret"; internal const string InstallId = "Install-ID"; - private readonly TimeSpan _requestTimeout = TimeSpan.FromMilliseconds(80000); //TODO not sure what to use here + private static readonly TimeSpan RequestTimeout = TimeSpan.FromMilliseconds(80000); //TODO not sure what to use here private const int MaximumCharactersDisplayedForAppSecret = 8; private string _baseLogUrl; private readonly IHttpNetworkAdapter _httpNetwork; - public IngestionHttp() : this(new HttpNetworkAdapter()) + public IngestionHttp() : this(new HttpNetworkAdapter(RequestTimeout)) { } public IngestionHttp(IHttpNetworkAdapter httpNetwork) { _httpNetwork = httpNetwork; - _httpNetwork.Timeout = _requestTimeout; } /// From 865b5073c6eacf0a25c1ede038f6c54cffb9cc73 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 19 May 2017 09:47:58 -0700 Subject: [PATCH 05/90] Make lock readonly and add comment --- .../Ingestion/Http/HttpNetworkAdapter.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/HttpNetworkAdapter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/HttpNetworkAdapter.cs index 66b27c0a0..b53cf9b80 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/HttpNetworkAdapter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/HttpNetworkAdapter.cs @@ -9,7 +9,7 @@ public sealed class HttpNetworkAdapter : IHttpNetworkAdapter { private HttpClient _httpClient; private TimeSpan? _timeout; - private object _lockObject = new object(); + private readonly object _lockObject = new object(); public HttpNetworkAdapter(TimeSpan? timeout = null) { @@ -38,7 +38,14 @@ private HttpClient HttpClient } } + /// + /// Asynchronously makes an HTTP request + /// + /// The request message + /// Cancellation token + /// Task containing the HTTP response /// + public async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) { try From 84deaa1c789fa0370680599397ab4012077e4759 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 19 May 2017 10:31:12 -0700 Subject: [PATCH 06/90] Replace regex parsing with simple string parsing to get app secret --- .../MobileCenter.cs | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/MobileCenter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/MobileCenter.cs index 6318ea67f..ef9c80c89 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/MobileCenter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/MobileCenter.cs @@ -5,10 +5,8 @@ namespace Microsoft.Azure.Mobile { public partial class MobileCenter { - /* - * Gets the first instance of an app secret corresponding to the given platform name, or returns the string - * as-is if no identifier can be found. Logs a message if no identifiers can be found. - */ + // Gets the first instance of an app secret corresponding to the given platform name, or returns the string + // as-is if no identifier can be found. Logs a message if no identifiers can be found. internal static string GetSecretForPlatform(string secrets, string platformIdentifier) { if (string.IsNullOrEmpty(secrets)) @@ -16,10 +14,8 @@ internal static string GetSecretForPlatform(string secrets, string platformIdent throw new MobileCenterException("App secrets string is null or empty"); } - /* - * If there are no colons, then there are no named identifiers, but log a message in case the developer made - * a typing error. - */ + // If there are no equals signs, then there are no named identifiers, but log a message in case the developer made + // a typing error. if (!secrets.Contains("=")) { MobileCenterLog.Debug(MobileCenterLog.LogTag, "No named identifier found in appSecret; using as-is"); @@ -28,28 +24,32 @@ internal static string GetSecretForPlatform(string secrets, string platformIdent var parseErrorMessage = $"Error parsing key for '{platformIdentifier}'"; - /* - * This assumes that the key contains only lowercase letters, digits, and hyphens - * (and that it has at least one character) - */ - var pattern = platformIdentifier + @"=([^;]+)"; - try + var platformIndicator = platformIdentifier + "="; + var secretIdx = secrets.IndexOf(platformIndicator, StringComparison.Ordinal) + platformIndicator.Length; + if (secretIdx == -1) { - var match = Regex.Match(secrets, pattern); - if (match.Value == string.Empty) - { - throw new MobileCenterException(parseErrorMessage); - } - return match.Groups[1].Value; + throw new MobileCenterException(parseErrorMessage); } - catch (ArgumentException e) + + var platformSecret = string.Empty; + + while (secretIdx < secrets.Length) { - throw new MobileCenterException(parseErrorMessage, e); + var nextChar = secrets[secretIdx++]; + if (nextChar == ';') + { + break; + } + + platformSecret += nextChar; } - catch (RegexMatchTimeoutException e) + + if (platformSecret == string.Empty) { - throw new MobileCenterException(parseErrorMessage, e); + throw new MobileCenterException(parseErrorMessage); } + + return platformSecret; } } } From abf3606c804ca63ee76c89f758989e0285f7af4c Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Fri, 19 May 2017 10:39:04 -0700 Subject: [PATCH 07/90] Remove unused using statement --- SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/MobileCenter.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/MobileCenter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/MobileCenter.cs index ef9c80c89..0d8457674 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/MobileCenter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/MobileCenter.cs @@ -1,5 +1,4 @@ using System; -using System.Text.RegularExpressions; namespace Microsoft.Azure.Mobile { From d5e1faf1868894e851b44ea0040c8b98301a3097 Mon Sep 17 00:00:00 2001 From: Guillaume Perrot Date: Fri, 19 May 2017 14:47:31 -0700 Subject: [PATCH 08/90] Start version 0.12.1 --- Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml | 2 +- Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs | 4 ++-- .../Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml | 2 +- .../Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs | 4 ++-- .../Contoso.Forms.Puppet.UWP/Package.appxmanifest | 2 +- .../Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs | 2 +- Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist | 4 ++-- .../Contoso.Forms.Puppet/Properties/AssemblyInfo.cs | 4 ++-- Apps/Contoso.UWP.Puppet/Package.appxmanifest | 2 +- Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs | 2 +- Apps/Contoso.iOS.Puppet/Info.plist | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs | 4 ++-- SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs | 2 +- .../Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs | 4 ++-- Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs | 4 ++-- Tests/Droid/Properties/AndroidManifest.xml | 2 +- Tests/Droid/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 ++-- Tests/iOS/Info.plist | 4 ++-- 53 files changed, 93 insertions(+), 93 deletions(-) diff --git a/Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml b/Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml index 3a7bd2942..0e3c0f86c 100644 --- a/Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml +++ b/Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs b/Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs index 5c272949c..b8356b0f5 100644 --- a/Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml index 48b539eb2..31d19995b 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs index c049e5b18..c4f968866 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs @@ -19,8 +19,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Package.appxmanifest b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Package.appxmanifest index 17786774c..601b410e4 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Package.appxmanifest +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Package.appxmanifest @@ -1,6 +1,6 @@ - + MobileCenter-Forms-UWP-Puppet diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs index 318e0f279..127402430 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] [assembly: ComVisible(false)] diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist index 44559d569..fcf9df1ee 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist @@ -5,9 +5,9 @@ CFBundleIdentifier com.microsoft.azure.mobile.xamarin.forms.puppet CFBundleShortVersionString - 0.12.0 + 0.12.1 CFBundleVersion - 0.12.0 + 0.12.1 LSRequiresIPhoneOS MinimumOSVersion diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Properties/AssemblyInfo.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Properties/AssemblyInfo.cs index 8e3c8137a..874b3df37 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/Apps/Contoso.UWP.Puppet/Package.appxmanifest b/Apps/Contoso.UWP.Puppet/Package.appxmanifest index 480d1ce97..2df9e6ecb 100644 --- a/Apps/Contoso.UWP.Puppet/Package.appxmanifest +++ b/Apps/Contoso.UWP.Puppet/Package.appxmanifest @@ -1,6 +1,6 @@ - + MobileCenter-UWP-Puppet diff --git a/Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs b/Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs index bf440299a..57623852b 100644 --- a/Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] [assembly: ComVisible(false)] \ No newline at end of file diff --git a/Apps/Contoso.iOS.Puppet/Info.plist b/Apps/Contoso.iOS.Puppet/Info.plist index d4e8c32a1..9c022aef1 100644 --- a/Apps/Contoso.iOS.Puppet/Info.plist +++ b/Apps/Contoso.iOS.Puppet/Info.plist @@ -7,9 +7,9 @@ CFBundleIdentifier com.microsoft.azure.mobile.xamarin.puppet CFBundleShortVersionString - 0.12.0 + 0.12.1 CFBundleVersion - 0.12.0 + 0.12.1 LSRequiresIPhoneOS MinimumOSVersion diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Properties/AssemblyInfo.cs index 1649dfb71..9bea918aa 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Properties/AssemblyInfo.cs @@ -26,5 +26,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs index fbb1b42d2..e0509eeb9 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs index 7a9a84358..bd3acdd13 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs @@ -5,6 +5,6 @@ public static class WrapperSdk public const string Name = "mobilecenter.xamarin"; /* We can't use reflection for assemblyInformationalVersion on iOS with "Link All" optimization. */ - internal const string Version = "0.12.0-SNAPSHOT"; + internal const string Version = "0.12.1-SNAPSHOT"; } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs index bccf1d8c1..d5b618b79 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs @@ -25,7 +25,7 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] [assembly: ComVisible(false)] [assembly: InternalsVisibleTo("Microsoft.Azure.Mobile.Test.UWP")] \ No newline at end of file diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS.Bindings/Properties/AssemblyInfo.cs index 35e4adc34..a8eb8be4f 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS.Bindings/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs index 5fff90c28..c02460393 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs @@ -23,5 +23,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs index 09866b4af..e5a4c86c7 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android.Bindings/Properties/AssemblyInfo.cs index 716575014..fdbe1c402 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android.Bindings/Properties/AssemblyInfo.cs @@ -18,8 +18,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android/Properties/AssemblyInfo.cs index 3eac1254f..240b4b7f5 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/Properties/AssemblyInfo.cs index b89ccbc55..22bf5ee63 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/Properties/AssemblyInfo.cs @@ -29,6 +29,6 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] [assembly: ComVisible(false)] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS.Bindings/Properties/AssemblyInfo.cs index eefd80f3b..d5dd62122 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS.Bindings/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS/Properties/AssemblyInfo.cs index d318be445..cd44f038e 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS/Properties/AssemblyInfo.cs @@ -23,5 +23,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics/Properties/AssemblyInfo.cs index 3955bc788..a097e6066 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android.Bindings/Properties/AssemblyInfo.cs index 8467500f0..1bab78c16 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android.Bindings/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android/Properties/AssemblyInfo.cs index 4481bf1fb..e4137d287 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android/Properties/AssemblyInfo.cs @@ -26,5 +26,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.UWP/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.UWP/Properties/AssemblyInfo.cs index 52da0247e..db479db27 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.UWP/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.UWP/Properties/AssemblyInfo.cs @@ -29,6 +29,6 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] [assembly: ComVisible(false)] \ No newline at end of file diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS.Bindings/Properties/AssemblyInfo.cs index 37841c077..760a1ed79 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS.Bindings/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS/Properties/AssemblyInfo.cs index 71bf75664..7e1741559 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS/Properties/AssemblyInfo.cs @@ -23,5 +23,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs index d452eeb5c..16ea38feb 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android.Bindings/Properties/AssemblyInfo.cs index faf9e68b2..558cf6878 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android.Bindings/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android/Properties/AssemblyInfo.cs index a786f6c4e..38e209c28 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS.Bindings/Properties/AssemblyInfo.cs index 4165c26a9..832775dc8 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS.Bindings/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS/Properties/AssemblyInfo.cs index 0b280b7dc..960b7f792 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute/Properties/AssemblyInfo.cs index 8905813ae..35301a476 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android.Bindings/Properties/AssemblyInfo.cs index 55e2a0ef3..aedb30567 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android.Bindings/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android/Properties/AssemblyInfo.cs index 2befd75a4..e9152cc10 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Properties/AssemblyInfo.cs index 263461fa3..b0e545fa2 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Properties/AssemblyInfo.cs @@ -28,5 +28,5 @@ [assembly: ReferenceAssembly] #endif [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] [assembly: ComVisible(false)] \ No newline at end of file diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS.Bindings/Properties/AssemblyInfo.cs index a2c7b5ab6..1fe553e3e 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS.Bindings/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS/Properties/AssemblyInfo.cs index 6b74c417e..a94e4acae 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs index 9e35e0167..96ba99a26 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs b/Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs index 9d724728e..9abc3dff4 100644 --- a/Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs +++ b/Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/Tests/Droid/Properties/AndroidManifest.xml b/Tests/Droid/Properties/AndroidManifest.xml index 166a87764..59eed5a90 100644 --- a/Tests/Droid/Properties/AndroidManifest.xml +++ b/Tests/Droid/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/Tests/Droid/Properties/AssemblyInfo.cs b/Tests/Droid/Properties/AssemblyInfo.cs index daaed4481..99d640649 100644 --- a/Tests/Droid/Properties/AssemblyInfo.cs +++ b/Tests/Droid/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.NET/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Analytics.NET/Properties/AssemblyInfo.cs index 67341811f..8146b9344 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.NET/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.NET/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] [assembly: InternalsVisibleTo("Microsoft.Azure.Mobile.Analytics.Test.Windows")] \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Properties/AssemblyInfo.cs index 43ba22fd8..c6a638a20 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Properties/AssemblyInfo.cs @@ -16,5 +16,5 @@ // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs index f3bdbf549..3622eba93 100644 --- a/Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] [assembly: InternalsVisibleTo("Microsoft.Azure.Mobile.Test.Windows")] diff --git a/Tests/Microsoft.Azure.Mobile.Push.NET/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Push.NET/Properties/AssemblyInfo.cs index 8fe99d6b2..ea56acc5e 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.NET/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Push.NET/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Properties/AssemblyInfo.cs index 4b5250f0d..cdc6e3be4 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] diff --git a/Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest b/Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest index 71ff5288d..50c2077ca 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest +++ b/Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest @@ -7,7 +7,7 @@ + Version="0.12.1.0" /> diff --git a/Tests/Microsoft.Azure.Mobile.Test.UWP/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Test.UWP/Properties/AssemblyInfo.cs index dcb48ffcb..60830c180 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.UWP/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.UWP/Properties/AssemblyInfo.cs @@ -14,5 +14,5 @@ // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] +[assembly: AssemblyFileVersion("0.12.1.0")] [assembly: ComVisible(false)] \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Properties/AssemblyInfo.cs index 80730992b..556c93726 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Properties/AssemblyInfo.cs @@ -16,5 +16,5 @@ // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.0.0")] -[assembly: AssemblyInformationalVersion("0.12.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] diff --git a/Tests/iOS/Info.plist b/Tests/iOS/Info.plist index 9ce67277f..1559f75f0 100644 --- a/Tests/iOS/Info.plist +++ b/Tests/iOS/Info.plist @@ -9,9 +9,9 @@ CFBundleIdentifier com.contoso.contoso-forms-test CFBundleShortVersionString - 0.12.0 + 0.12.1 CFBundleVersion - 0.12.0 + 0.12.1 LSRequiresIPhoneOS MinimumOSVersion From d1d3958f63d1204d04bf71b1237168492e289430 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Mon, 22 May 2017 14:59:33 +0300 Subject: [PATCH 09/90] Make internal APIs that do work on background threads return tasks --- .../Channel/Channel.cs | 263 ++++++++---------- .../Channel/ChannelGroup.cs | 25 +- .../Channel/IChannel.cs | 4 +- .../Channel/IChannelUnit.cs | 2 +- .../Ingestion/Http/NetworkStateIngestion.cs | 2 +- .../Ingestion/Http/NetworkStateServiceCall.cs | 27 +- .../Ingestion/Http/RetryableIngestion.cs | 2 +- .../Ingestion/Http/RetryableServiceCall.cs | 36 +-- .../Ingestion/Http/ServiceCallDecorator.cs | 16 +- .../Ingestion/IServiceCall.cs | 9 +- .../Ingestion/ServiceCall.cs | 18 +- .../MobileCenter.cs | 8 +- .../MobileCenterService.cs | 4 +- .../Storage/IStorage.cs | 2 +- .../Storage/IStorageAdapter.cs | 1 - .../Storage/Storage.cs | 7 +- .../Storage/TaskLockSource.cs | 6 +- .../Analytics.cs | 2 +- .../Channel/SessionTracker.cs | 2 +- .../Microsoft.Azure.Mobile.Push.UWP/Push.cs | 2 +- .../AnalyticsTest.cs | 20 +- .../SessionTrackerTest.cs | 10 +- .../Channel/ChannelGroupTest.cs | 12 +- .../Channel/ChannelTest.cs | 55 ++-- .../Ingestion/Http/RetryableTest.cs | 57 +--- .../Ingestion/Http/ServiceCallTest.cs | 58 +--- .../MobileCenterServiceTest.cs | 6 +- .../MobileCenterTest.cs | 10 +- .../Storage/FakeStorageTest.cs | 8 +- .../Storage/MockStorage.cs | 4 +- .../Storage/StorageTest.cs | 4 +- 31 files changed, 253 insertions(+), 429 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs index f01ac0168..6474d1530 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs @@ -46,9 +46,9 @@ internal Channel(string name, int maxLogsPerBatch, TimeSpan batchTimeInterval, i Task.Run(CountFromDiskAsync); } - public void SetEnabled(bool enabled) + public async Task SetEnabledAsync(bool enabled) { - _mutex.Lock(); + await _mutex.LockAsync().ConfigureAwait(false); try { if (_enabled == enabled) @@ -60,11 +60,16 @@ public void SetEnabled(bool enabled) _enabled = true; _discardLogs = false; _stateKeeper.InvalidateState(); - CheckPendingLogs(); + var stateSnapshot = _stateKeeper.GetStateSnapshot(); + + // We need count logs from storage here because CountFromDiskAsync may be aborted. + var logCount = await _storage.CountLogsAsync(Name).ConfigureAwait(false); + _pendingLogCount = logCount; + await CheckPendingLogs(stateSnapshot).ConfigureAwait(false); } else { - Suspend(true, new CancellationException()); + await Suspend(true, new CancellationException()).ConfigureAwait(false); } } finally @@ -104,37 +109,30 @@ public bool IsEnabled public event EventHandler FailedToSendLog; #endregion - public Task Enqueue(Log log) + public async Task EnqueueAsync(Log log) { - _mutex.Lock(); - var stateSnapshot = _stateKeeper.GetStateSnapshot(); try { + await _mutex.LockAsync().ConfigureAwait(false); + var stateSnapshot = _stateKeeper.GetStateSnapshot(); if (_discardLogs) { MobileCenterLog.Warn(MobileCenterLog.LogTag, "Channel is disabled; logs are discarded"); _mutex.Unlock(); SendingLog?.Invoke(this, new SendingLogEventArgs(log)); FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, new CancellationException())); - return null; } _mutex.Unlock(); EnqueuingLog?.Invoke(this, new EnqueuingLogEventArgs(log)); - _mutex.Lock(stateSnapshot); - return Task.Run(async () => + await Task.Run(async () => { await PrepareLogAsync(log).ConfigureAwait(false); await PersistLogAsync(log, stateSnapshot).ConfigureAwait(false); - }); + }).ConfigureAwait(false); } catch (StatefulMutexException e) { MobileCenterLog.Warn(MobileCenterLog.LogTag, "The Enqueue operation has been cancelled", e); - return null; - } - finally - { - _mutex.Unlock(); } } @@ -168,7 +166,7 @@ private async Task PersistLogAsync(Log log, State stateSnapshot) _pendingLogCount++; if (_enabled) { - CheckPendingLogs(); + await CheckPendingLogs(stateSnapshot).ConfigureAwait(false); return; } MobileCenterLog.Warn(MobileCenterLog.LogTag, "Channel is temporarily disabled; log was saved to disk"); @@ -190,39 +188,42 @@ public void InvalidateDeviceCache() _mutex.Unlock(); } - public void Clear() + public async Task ClearAsync() { + await _mutex.LockAsync().ConfigureAwait(false); var stateSnapshot = _stateKeeper.GetStateSnapshot(); - _storage.DeleteLogsAsync(Name).ContinueWith(completedTask => + try { - try - { - _mutex.Lock(stateSnapshot); - _pendingLogCount = 0; - _mutex.Unlock(); - } - catch (StatefulMutexException) - { - //Nothing to handle - } - }); + await _storage.DeleteLogsAsync(Name).ConfigureAwait(false); + _pendingLogCount = 0; + } + catch (StatefulMutexException e) + { + MobileCenterLog.Warn(MobileCenterLog.LogTag, "The Clear operation has been cancelled", e); + } + finally + { + _mutex.Unlock(); + } } private async Task CountFromDiskAsync() { - await _mutex.LockAsync().ConfigureAwait(false); - var stateSnapshot = _stateKeeper.GetStateSnapshot(); - _mutex.Unlock(); - var logCount = await _storage.CountLogsAsync(Name).ConfigureAwait(false); try { + await _mutex.LockAsync().ConfigureAwait(false); + var stateSnapshot = _stateKeeper.GetStateSnapshot(); + _mutex.Unlock(); + var logCount = await _storage.CountLogsAsync(Name).ConfigureAwait(false); await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); _pendingLogCount = logCount; - CheckPendingLogs(); + await CheckPendingLogs(stateSnapshot).ConfigureAwait(false); } - catch (StatefulMutexException e) + catch (StatefulMutexException) { - MobileCenterLog.Warn(MobileCenterLog.LogTag, "The CountFromDisk operation has been cancelled", e); + // The CountFromDisk operation has been cancelled. + // This may happen when we call Shutdown right after constructor. + // We will call CountLogs when channel will be enabled again. } finally { @@ -230,7 +231,7 @@ private async Task CountFromDiskAsync() } } - private Task Suspend(bool deleteLogs, Exception exception) + private async Task Suspend(bool deleteLogs, Exception exception) { _enabled = false; _batchScheduled = false; @@ -259,21 +260,19 @@ private Task Suspend(bool deleteLogs, Exception exception) if (deleteLogs) { _pendingLogCount = 0; - return Task.Run(DeleteLogsOnSuspendedAsync); + await DeleteLogsOnSuspendedAsync(stateSnapshot).ConfigureAwait(false); + return; } - return _storage.ClearPendingLogStateAsync(Name); + await _storage.ClearPendingLogStateAsync(Name).ConfigureAwait(false); } catch (StatefulMutexException e) { MobileCenterLog.Warn(MobileCenterLog.LogTag, "The CountFromDisk operation has been cancelled", e); - return null; } } - private async Task DeleteLogsOnSuspendedAsync() + private async Task DeleteLogsOnSuspendedAsync(State stateSnapshot) { - await _mutex.LockAsync().ConfigureAwait(false); - var stateSnapshot = _stateKeeper.GetStateSnapshot(); try { if (SendingLog != null || FailedToSendLog != null) @@ -286,15 +285,6 @@ private async Task DeleteLogsOnSuspendedAsync() MobileCenterLog.Warn(MobileCenterLog.LogTag, "Failed to invoke events for logs being deleted."); return; } - catch (StatefulMutexException e) - { - MobileCenterLog.Warn(MobileCenterLog.LogTag, "The DeleteLogs operation has been cancelled", e); - return; - } - finally - { - _mutex.Unlock(); - } await _storage.DeleteLogsAsync(Name).ConfigureAwait(false); } @@ -317,49 +307,37 @@ private async Task SignalDeletingLogs(State stateSnapshot) } } - private async Task TriggerIngestionAsync() + private async Task TriggerIngestionAsync(State stateSnapshot) { - await _mutex.LockAsync().ConfigureAwait(false); - var stateSnapshot = _stateKeeper.GetStateSnapshot(); - try + if (!_enabled) { - if (!_enabled) - { - return; - } - MobileCenterLog.Debug(MobileCenterLog.LogTag, - $"triggerIngestion({Name}) pendingLogCount={_pendingLogCount}"); - _batchScheduled = false; - if (_sendingBatches.Count >= _maxParallelBatches) - { - MobileCenterLog.Debug(MobileCenterLog.LogTag, - "Already sending " + _maxParallelBatches + " batches of analytics data to the server"); - return; - } - - // Get a batch from storage - var logs = new List(); - _mutex.Unlock(); - var batchId = await _storage.GetLogsAsync(Name, _maxLogsPerBatch, logs).ConfigureAwait(false); - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); - if (batchId != null) - { - _sendingBatches.Add(batchId, logs); - _pendingLogCount -= logs.Count; - TriggerIngestion(logs, stateSnapshot, batchId); - } + return; } - catch (StatefulMutexException e) + MobileCenterLog.Debug(MobileCenterLog.LogTag, + $"triggerIngestion({Name}) pendingLogCount={_pendingLogCount}"); + _batchScheduled = false; + if (_sendingBatches.Count >= _maxParallelBatches) { - MobileCenterLog.Warn(MobileCenterLog.LogTag, "The TriggerIngestion operation has been cancelled", e); + MobileCenterLog.Debug(MobileCenterLog.LogTag, + "Already sending " + _maxParallelBatches + " batches of analytics data to the server"); + return; } - finally + + // Get a batch from storage + var logs = new List(); + _mutex.Unlock(); + var batchId = await _storage.GetLogsAsync(Name, _maxLogsPerBatch, logs).ConfigureAwait(false); + await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); + if (batchId != null) { - _mutex.Unlock(); + _sendingBatches.Add(batchId, logs); + _pendingLogCount -= logs.Count; + await TriggerIngestion(logs, stateSnapshot, batchId).ConfigureAwait(false); + await CheckPendingLogs(stateSnapshot).ConfigureAwait(false); } } - private void TriggerIngestion(IList logs, State stateSnapshot, string batchId) + private async Task TriggerIngestion(IList logs, State stateSnapshot, string batchId) { // Before sending logs, trigger the sending event for this channel if (SendingLog != null) @@ -373,54 +351,41 @@ private void TriggerIngestion(IList logs, State stateSnapshot, string batch } // If the optional Install ID has no value, default to using empty GUID var installId = MobileCenter.InstallId.HasValue ? MobileCenter.InstallId.Value : Guid.Empty; - var serviceCall = _ingestion.PrepareServiceCall(_appSecret, installId, logs); - - serviceCall.ServiceCallFailedCallback = exception => - { - serviceCall.Dispose(); - HandleSendingFailure(batchId, exception); - }; - - serviceCall.ServiceCallSucceededCallback = async () => + using (var serviceCall = _ingestion.PrepareServiceCall(_appSecret, installId, logs)) { - serviceCall.Dispose(); - if (!_stateKeeper.IsCurrent(stateSnapshot)) - { - return; - } try { - await _storage.DeleteLogsAsync(Name, batchId).ConfigureAwait(false); + await serviceCall.ExecuteAsync().ConfigureAwait(false); } - catch (StorageException e) - { - MobileCenterLog.Warn(MobileCenterLog.LogTag, $"Could not delete logs for batch {batchId}", e); - } - try - { - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); - var removedLogs = _sendingBatches[batchId]; - _sendingBatches.Remove(batchId); - if (SentLog != null) - { - foreach (var log in removedLogs) - { - _mutex.Unlock(); - SentLog?.Invoke(this, new SentLogEventArgs(log)); - _mutex.Lock(stateSnapshot); - } - } - CheckPendingLogs(); - } - catch (StatefulMutexException) + catch (IngestionException exception) { + HandleSendingFailure(batchId, exception); + return; } - finally + } + if (!_stateKeeper.IsCurrent(stateSnapshot)) + { + return; + } + try + { + await _storage.DeleteLogsAsync(Name, batchId).ConfigureAwait(false); + } + catch (StorageException e) + { + MobileCenterLog.Warn(MobileCenterLog.LogTag, $"Could not delete logs for batch {batchId}", e); + } + var removedLogs = _sendingBatches[batchId]; + _sendingBatches.Remove(batchId); + if (SentLog != null) + { + foreach (var log in removedLogs) { _mutex.Unlock(); + SentLog?.Invoke(this, new SentLogEventArgs(log)); + _mutex.Lock(stateSnapshot); } - }; - serviceCall.Execute(); + } } private void HandleSendingFailure(string batchId, IngestionException e) @@ -436,53 +401,61 @@ private void HandleSendingFailure(string batchId, IngestionException e) FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, e)); } } - _mutex.Lock(); - try + Suspend(!isRecoverable, e); + if (isRecoverable) { - Suspend(!isRecoverable, e); - if (isRecoverable) - { - _pendingLogCount += removedLogs.Count; - } - } - finally - { - _mutex.Unlock(); + _pendingLogCount += removedLogs.Count; } } - private void CheckPendingLogs() + private async Task CheckPendingLogs(State stateSnapshot) { if (!_enabled) { MobileCenterLog.Info(MobileCenterLog.LogTag, "The service has been disabled. Stop processing logs."); - return; } MobileCenterLog.Debug(MobileCenterLog.LogTag, $"CheckPendingLogs({Name}) pending log count: {_pendingLogCount}"); if (_pendingLogCount >= _maxLogsPerBatch) { - Task.Run(TriggerIngestionAsync); + await TriggerIngestionAsync(stateSnapshot).ConfigureAwait(false); } else if (_pendingLogCount > 0 && !_batchScheduled) { _batchScheduled = true; - Task.Delay((int)_batchTimeInterval.TotalMilliseconds).ContinueWith(async completedTask => + + // No need wait _batchTimeInterval here. +#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed + Task.Run(async () => { + await Task.Delay((int)_batchTimeInterval.TotalMilliseconds).ConfigureAwait(false); if (_batchScheduled) { - await TriggerIngestionAsync().ConfigureAwait(false); + try + { + await _mutex.LockAsync().ConfigureAwait(false); + await TriggerIngestionAsync(_stateKeeper.GetStateSnapshot()).ConfigureAwait(false); + } + catch (StatefulMutexException e) + { + MobileCenterLog.Warn(MobileCenterLog.LogTag, "The TriggerIngestion operation has been cancelled", e); + } + finally + { + _mutex.Unlock(); + } } }); +#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed } } - public Task Shutdown() + public async Task ShutdownAsync() { - _mutex.Lock(); + await _mutex.LockAsync().ConfigureAwait(false); try { - return Suspend(false, new CancellationException()); + await Suspend(false, new CancellationException()).ConfigureAwait(false); } finally { diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/ChannelGroup.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/ChannelGroup.cs index f9f73d5d6..87eeaa4eb 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/ChannelGroup.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/ChannelGroup.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; -using System.Threading; +using System.Threading.Tasks; using Microsoft.Azure.Mobile.Ingestion; using Microsoft.Azure.Mobile.Ingestion.Http; using Microsoft.Azure.Mobile.Storage; -using System.Threading.Tasks; namespace Microsoft.Azure.Mobile.Channel { @@ -78,19 +77,21 @@ public void AddChannel(IChannelUnit channel) } } - public void SetEnabled(bool enabled) + public Task SetEnabledAsync(bool enabled) { ThrowIfDisposed(); + var tasks = new List(); lock (_channelGroupLock) { foreach (var channel in _channels) { - channel.SetEnabled(enabled); + tasks.Add(channel.SetEnabledAsync(enabled)); } } + return Task.WhenAll(tasks); } - public Task Shutdown() + public async Task ShutdownAsync() { ThrowIfDisposed(); var tasks = new List(); @@ -98,15 +99,15 @@ public Task Shutdown() { foreach (var channel in _channels) { - tasks.Add(channel.Shutdown()); - } - MobileCenterLog.Debug(MobileCenterLog.LogTag, "Waiting for storage to finish operations"); - if (!_storage.Shutdown(_shutdownTimeout)) - { - MobileCenterLog.Warn(MobileCenterLog.LogTag, "Storage taking too long to finish operations; shutting down channel without waiting any longer."); + tasks.Add(channel.ShutdownAsync()); } } - return Task.WhenAll(tasks); + await Task.WhenAll(tasks).ConfigureAwait(false); + MobileCenterLog.Debug(MobileCenterLog.LogTag, "Waiting for storage to finish operations"); + if (!await _storage.ShutdownAsync(_shutdownTimeout).ConfigureAwait(false)) + { + MobileCenterLog.Warn(MobileCenterLog.LogTag, "Storage taking too long to finish operations; shutting down channel without waiting any longer."); + } } private static IIngestion DefaultIngestion() diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/IChannel.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/IChannel.cs index 3101db5af..07196ca97 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/IChannel.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/IChannel.cs @@ -32,11 +32,11 @@ public interface IChannel : IDisposable /// Enable or disable the channel /// /// Value indicating whether channel should be enabled or disabled - void SetEnabled(bool enabled); + Task SetEnabledAsync(bool enabled); /// /// Stop all calls in progress and deactivate this channel /// - Task Shutdown(); + Task ShutdownAsync(); } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/IChannelUnit.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/IChannelUnit.cs index c6ef4d529..9af21f7fb 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/IChannelUnit.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/IChannelUnit.cs @@ -10,6 +10,6 @@ public interface IChannelUnit : IChannel /// Enqueue a log for processing /// /// - Task Enqueue(Log log); + Task EnqueueAsync(Log log); } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/NetworkStateIngestion.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/NetworkStateIngestion.cs index eeb3cec9b..cdfe2b4b0 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/NetworkStateIngestion.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/NetworkStateIngestion.cs @@ -39,7 +39,7 @@ private void HandleNetworkAddressChanged(object sender, EventArgs e) foreach (var call in callsCopy) { _calls.Remove(call); - call.Execute(); + call.ExecuteAsync(); } } else diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/NetworkStateServiceCall.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/NetworkStateServiceCall.cs index 242b17d20..dc1abc4c6 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/NetworkStateServiceCall.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/NetworkStateServiceCall.cs @@ -1,3 +1,6 @@ +using System; +using System.Threading.Tasks; + namespace Microsoft.Azure.Mobile.Ingestion.Http { public class NetworkStateServiceCall : ServiceCallDecorator @@ -9,24 +12,20 @@ public NetworkStateServiceCall(IServiceCall decoratedApi, NetworkStateIngestion _networkIngestion = networkIngestion; } - public override void Execute() + public override async Task ExecuteAsync() { - _networkIngestion.ExecuteCallAsync(DecoratedApi).ContinueWith(completedTask => + try { - if (completedTask.IsFaulted) - { - var innerException = completedTask.Exception?.InnerException; - if (innerException is NetworkUnavailableException) - { - return; - } - ServiceCallFailedCallback?.Invoke(innerException as IngestionException); - } - else + await _networkIngestion.ExecuteCallAsync(DecoratedApi).ConfigureAwait(false); + } + catch (Exception exception) + { + if (exception is NetworkUnavailableException) { - ServiceCallSucceededCallback?.Invoke(); + return; } - }); + throw exception; + } } } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableIngestion.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableIngestion.cs index 3c51f7dab..d1509d849 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableIngestion.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableIngestion.cs @@ -54,7 +54,7 @@ public override async Task ExecuteCallAsync(IServiceCall call) await base.ExecuteCallAsync(call).ConfigureAwait(false); return; } - await retryableCall.RunWithRetriesAsync().ConfigureAwait(false); + await retryableCall.ExecuteAsync().ConfigureAwait(false); } private static Func GetDelayFunc(TimeSpan[] intervals, int retry) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableServiceCall.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableServiceCall.cs index 42e32863b..3f54827a5 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableServiceCall.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableServiceCall.cs @@ -18,21 +18,6 @@ public RetryableServiceCall(IServiceCall decoratedApi, Func[] retryInterva _retryIntervals = retryIntervals; } - /// - public async Task RunWithRetriesAsync() - { - await _mutex.WaitAsync().ConfigureAwait(false); - try - { - _tokenSource = new CancellationTokenSource(); - await RunWithRetriesAsyncHelper().ConfigureAwait(false); - } - finally - { - _mutex.Release(); - } - } - /// private async Task RunWithRetriesAsyncHelper() { @@ -61,19 +46,18 @@ public override void Cancel() _tokenSource?.Cancel(); } - public override void Execute() + public override async Task ExecuteAsync() { - RunWithRetriesAsync().ContinueWith(completedTask => + await _mutex.WaitAsync().ConfigureAwait(false); + try { - if (completedTask.IsFaulted) - { - ServiceCallFailedCallback?.Invoke(completedTask.Exception?.InnerException as IngestionException); - } - else - { - ServiceCallSucceededCallback?.Invoke(); - } - }); + _tokenSource = new CancellationTokenSource(); + await RunWithRetriesAsyncHelper().ConfigureAwait(false); + } + finally + { + _mutex.Release(); + } } protected override void Dispose(bool disposing) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/ServiceCallDecorator.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/ServiceCallDecorator.cs index b58d147fb..56f46ef1e 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/ServiceCallDecorator.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/ServiceCallDecorator.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using Microsoft.Azure.Mobile.Ingestion.Models; namespace Microsoft.Azure.Mobile.Ingestion.Http @@ -15,24 +16,13 @@ public abstract class ServiceCallDecorator : IServiceCall public Guid InstallId => DecoratedApi.InstallId; public virtual CancellationToken CancellationToken => DecoratedApi.CancellationToken; - public ServiceCallFailedHandler ServiceCallFailedCallback - { - get { return DecoratedApi.ServiceCallFailedCallback; } - set { DecoratedApi.ServiceCallFailedCallback = value; } - } - public Action ServiceCallSucceededCallback - { - get { return DecoratedApi.ServiceCallSucceededCallback; } - set { DecoratedApi.ServiceCallSucceededCallback = value; } - } - protected ServiceCallDecorator(IServiceCall decoratedApi) { DecoratedApi = decoratedApi; } - public virtual void Execute() + public virtual Task ExecuteAsync() { - DecoratedApi.Execute(); + return DecoratedApi.ExecuteAsync(); } public virtual void Cancel() diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/IServiceCall.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/IServiceCall.cs index df8d75b13..9379c3d85 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/IServiceCall.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/IServiceCall.cs @@ -1,12 +1,11 @@ using System; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using Microsoft.Azure.Mobile.Ingestion.Models; namespace Microsoft.Azure.Mobile.Ingestion { - public delegate void ServiceCallFailedHandler(IngestionException exception); - public interface IServiceCall : IDisposable { IIngestion Ingestion { get; } @@ -14,9 +13,9 @@ public interface IServiceCall : IDisposable string AppSecret { get; } Guid InstallId { get; } CancellationToken CancellationToken { get; } - void Execute(); + + /// + Task ExecuteAsync(); void Cancel(); - ServiceCallFailedHandler ServiceCallFailedCallback { get; set; } - Action ServiceCallSucceededCallback { get; set; } } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/ServiceCall.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/ServiceCall.cs index d64f03478..9512be8e5 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/ServiceCall.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/ServiceCall.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using System.Threading; +using System.Threading.Tasks; using Microsoft.Azure.Mobile.Ingestion.Models; namespace Microsoft.Azure.Mobile.Ingestion.Http @@ -16,9 +17,6 @@ public abstract class ServiceCall : IServiceCall public CancellationToken CancellationToken => _tokenSource.Token; - public ServiceCallFailedHandler ServiceCallFailedCallback { get; set; } - public Action ServiceCallSucceededCallback { get; set; } - protected ServiceCall(IIngestion ingestion, IList logs, string appSecret, Guid installId) { Ingestion = ingestion; @@ -32,21 +30,11 @@ public virtual void Cancel() _tokenSource.Cancel(); } - public virtual void Execute() + public virtual async Task ExecuteAsync() { _tokenSource.Dispose(); _tokenSource = new CancellationTokenSource(); - Ingestion.ExecuteCallAsync(this).ContinueWith(completedTask => - { - if (completedTask.IsFaulted) - { - ServiceCallFailedCallback?.Invoke(completedTask.Exception?.InnerException as IngestionException); - } - else - { - ServiceCallSucceededCallback?.Invoke(); - } - }); + await Ingestion.ExecuteCallAsync(this).ConfigureAwait(false); } public void Dispose() diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs index 44c13dc52..d9527a234 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs @@ -241,7 +241,7 @@ private bool InstanceEnabled return; } - _channelGroup?.SetEnabled(value); + _channelGroup?.SetEnabledAsync(value); _applicationSettings[EnabledKey] = value; foreach (var service in _services) @@ -267,7 +267,7 @@ private void SetInstanceCustomProperties(CustomProperties customProperties) } var customPropertiesLog = new CustomPropertiesLog(); customPropertiesLog.Properties = customProperties.Properties; - _channel.Enqueue(customPropertiesLog); + _channel.EnqueueAsync(customPropertiesLog); } // Internal for testing @@ -284,7 +284,7 @@ internal void InstanceConfigure(string appSecretOrSecrets) _channelGroup = _channelGroupFactory?.CreateChannelGroup(_appSecret) ?? new ChannelGroup(_appSecret); _applicationLifecycleHelper = new ApplicationLifecycleHelper(); - _applicationLifecycleHelper.UnhandledExceptionOccurred += (sender, e) => _channelGroup.Shutdown(); + _applicationLifecycleHelper.UnhandledExceptionOccurred += (sender, e) => _channelGroup.ShutdownAsync(); _channel = _channelGroup.AddChannel(ChannelName, Constants.DefaultTriggerCount, Constants.DefaultTriggerInterval, Constants.DefaultTriggerMaxParallelRequests); if (_logUrl != null) @@ -342,7 +342,7 @@ internal void StartInstance(params Type[] services) // Enqueue a log indicating which services have been initialized if (startServiceLog.Services.Count > 0) { - _channel.Enqueue(startServiceLog); + _channel.EnqueueAsync(startServiceLog); } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenterService.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenterService.cs index ede5aa5fa..f7913b9ad 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenterService.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenterService.cs @@ -97,7 +97,7 @@ public virtual bool InstanceEnabled MobileCenterLog.Info(LogTag, $"{ServiceName} service has already been {enabledString}."); return; } - Channel?.SetEnabled(value); + Channel?.SetEnabledAsync(value); _applicationSettings[EnabledPreferenceKey] = value; MobileCenterLog.Info(LogTag, $"{ServiceName} service has been {enabledString}"); } @@ -118,7 +118,7 @@ public virtual void OnChannelGroupReady(IChannelGroup channelGroup, string appSe Channel = channelGroup.AddChannel(ChannelName, TriggerCount, TriggerInterval, TriggerMaxParallelRequests); var enabled = MobileCenter.Enabled && InstanceEnabled; _applicationSettings[EnabledPreferenceKey] = enabled; - Channel.SetEnabled(enabled); + Channel.SetEnabledAsync(enabled); } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/IStorage.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/IStorage.cs index 09bc26c27..2183d2cad 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/IStorage.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/IStorage.cs @@ -13,6 +13,6 @@ public interface IStorage : IDisposable Task CountLogsAsync(string channelName); Task ClearPendingLogStateAsync(string channelName); Task GetLogsAsync(string channelName, int limit, List logs); - bool Shutdown(TimeSpan timeout); + Task ShutdownAsync(TimeSpan timeout); } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/IStorageAdapter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/IStorageAdapter.cs index 167c1a41e..0c073bd8a 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/IStorageAdapter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/IStorageAdapter.cs @@ -1,7 +1,6 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; -using System.Text; using System.Threading.Tasks; namespace Microsoft.Azure.Mobile.Storage diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs index 9398487af..b168c2771 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs @@ -1,8 +1,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; -using System.Threading; using Newtonsoft.Json; using Microsoft.Azure.Mobile.Ingestion.Models; using SQLite; @@ -261,10 +259,9 @@ private async Task InitializeDatabaseAsync() /// /// The maximum amount of time to wait for remaining tasks /// True if remaining tasks completed in time; false otherwise - /// This method blocks the calling thread - public bool Shutdown(TimeSpan timeout) + public Task ShutdownAsync(TimeSpan timeout) { - return _taskLockSource.Shutdown(timeout); + return _taskLockSource.ShutdownAsync(timeout); } private static string GetFullIdentifier(string channelName, string identifier) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs index 688491d27..6488a42cf 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs @@ -1,6 +1,4 @@ using System; -using System.Collections.Generic; -using System.Text; using System.Threading; using System.Threading.Tasks; @@ -16,13 +14,13 @@ public class TaskLockSource : IDisposable private bool _isShutdown; private int _numTasksRemaning; - public bool Shutdown(TimeSpan timeout) + public Task ShutdownAsync(TimeSpan timeout) { lock (_lockObject) { _isShutdown = true; } - return _taskSemaphore.Wait(timeout); + return _taskSemaphore.WaitAsync(timeout); } public TaskLock GetTaskLock() diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Analytics.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Analytics.cs index e30b99a01..e0c285694 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Analytics.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Analytics.cs @@ -140,7 +140,7 @@ private void InstanceTrackEvent(string name, IDictionary propert { properties = ValidateProperties(properties, name, type); var log = new EventLog(0, null, Guid.NewGuid(), name, null, properties); - Channel.Enqueue(log); + Channel.EnqueueAsync(log); } } } diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Channel/SessionTracker.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Channel/SessionTracker.cs index 1b7d00c7a..54e6caf80 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Channel/SessionTracker.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Channel/SessionTracker.cs @@ -134,7 +134,7 @@ private void SendStartSessionIfNeeded() _sessions.Add(now, _sid.Value); _applicationSettings[StorageKey] = SessionsAsString(); var startSessionLog = new StartSessionLog { Sid = _sid }; - _channel.Enqueue(startSessionLog); + _channel.EnqueueAsync(startSessionLog); } private string SessionsAsString() diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs index 309004568..e88ca8216 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs @@ -88,7 +88,7 @@ private void ApplyEnabledState(bool enabled) // Send channel URI to backend MobileCenterLog.Debug(LogTag, $"Push token '{pushToken}'"); var pushInstallationLog = new PushInstallationLog(0, null, pushToken, Guid.NewGuid()); - await Channel.Enqueue(pushInstallationLog).ConfigureAwait(false); + await Channel.EnqueueAsync(pushInstallationLog).ConfigureAwait(false); } else { diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/AnalyticsTest.cs b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/AnalyticsTest.cs index 52887b750..4a03317e7 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/AnalyticsTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/AnalyticsTest.cs @@ -161,7 +161,7 @@ public void TrackEvent() var properties = new Dictionary {{key, val}}; Analytics.TrackEvent(eventName, properties); - _mockChannel.Verify(channel => channel.Enqueue(It.Is(log => + _mockChannel.Verify(channel => channel.EnqueueAsync(It.Is(log => log.Name == eventName && log.Properties != null && log.Properties.Count == 1 && @@ -180,38 +180,38 @@ public void TrackEventInvalid() // Event name is null or empty Analytics.TrackEvent(null); Analytics.TrackEvent(""); - _mockChannel.Verify(channel => channel.Enqueue(It.IsAny()), Times.Never()); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); // Event name exceeds max length Analytics.TrackEvent(new string('?', 257)); - _mockChannel.Verify(channel => channel.Enqueue(It.IsAny()), Times.Never()); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); // Without properties Analytics.TrackEvent("test", null); - _mockChannel.Verify(channel => channel.Enqueue(It.IsAny()), Times.Once()); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Once()); // Property key is null or empty _mockChannel.ResetCalls(); Analytics.TrackEvent("test", new Dictionary { { "", "test" } }); - _mockChannel.Verify(channel => channel.Enqueue(It.Is(log => + _mockChannel.Verify(channel => channel.EnqueueAsync(It.Is(log => log.Properties == null || log.Properties.Count == 0)), Times.Once()); // Property key length exceeds maximum _mockChannel.ResetCalls(); Analytics.TrackEvent("test", new Dictionary { { new string('?', 65), "test" } }); - _mockChannel.Verify(channel => channel.Enqueue(It.Is(log => + _mockChannel.Verify(channel => channel.EnqueueAsync(It.Is(log => log.Properties == null || log.Properties.Count == 0)), Times.Once()); // Property value is null _mockChannel.ResetCalls(); Analytics.TrackEvent("test", new Dictionary { { "test", null } }); - _mockChannel.Verify(channel => channel.Enqueue(It.Is(log => + _mockChannel.Verify(channel => channel.EnqueueAsync(It.Is(log => log.Properties == null || log.Properties.Count == 0)), Times.Once()); // Property value length exceeds maximum _mockChannel.ResetCalls(); Analytics.TrackEvent("test", new Dictionary { { "test", new string('?', 65) } }); - _mockChannel.Verify(channel => channel.Enqueue(It.Is(log => + _mockChannel.Verify(channel => channel.EnqueueAsync(It.Is(log => log.Properties == null || log.Properties.Count == 0)), Times.Once()); // Properties size exceeds maximum @@ -222,7 +222,7 @@ public void TrackEventInvalid() manyProperties["test" + i] = "test" + i; } Analytics.TrackEvent("test", manyProperties); - _mockChannel.Verify(channel => channel.Enqueue(It.Is(log => + _mockChannel.Verify(channel => channel.EnqueueAsync(It.Is(log => log.Properties.Count == 5)), Times.Once()); } @@ -236,7 +236,7 @@ public void TrackEventWhileDisabled() Analytics.Enabled = false; Analytics.TrackEvent("anevent"); - _mockChannel.Verify(channel => channel.Enqueue(It.IsAny()), Times.Never()); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); } } } diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs index b21ff986a..fc9eb75fe 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs @@ -38,7 +38,7 @@ public void ResumeFirstTime() { _sessionTracker.Resume(); - _mockChannel.Verify(channel => channel.Enqueue(It.IsAny()), Times.Once()); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Once()); } /// @@ -52,7 +52,7 @@ public void ResumeAfterTimeout() Task.Delay((int)SessionTracker.SessionTimeout).Wait(); _sessionTracker.Resume(); - _mockChannel.Verify(channel => channel.Enqueue(It.IsAny()), Times.Exactly(2)); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Exactly(2)); } /// @@ -65,7 +65,7 @@ public void ResumeAfterShortPause() _sessionTracker.Pause(); _sessionTracker.Resume(); - _mockChannel.Verify(channel => channel.Enqueue(It.IsAny()), Times.Once()); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Once()); } /// @@ -120,7 +120,7 @@ public void HandleEnqueuingLogOutsideSession() var eventArgs = new EnqueuingLogEventArgs(eventLog); _mockChannelGroup.Raise(group => group.EnqueuingLog += null, null, eventArgs); - _mockChannel.Verify(channel => channel.Enqueue(It.IsAny()), Times.Once()); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Once()); Assert.IsNotNull(eventLog.Sid); } @@ -135,7 +135,7 @@ public void HandleEnqueuingStartSessionLog() var eventArgs = new EnqueuingLogEventArgs(sessionLog); _mockChannelGroup.Raise(group => group.EnqueuingLog += null, null, eventArgs); - _mockChannel.Verify(channel => channel.Enqueue(It.IsAny()), Times.Never()); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); } /// diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelGroupTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelGroupTest.cs index dddc4066a..74dce266a 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelGroupTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelGroupTest.cs @@ -148,13 +148,13 @@ public void TestEnableChannelGroup() { _channelGroup.AddChannel(mockedChannel); } - _channelGroup.SetEnabled(true); - _channelGroup.SetEnabled(false); + _channelGroup.SetEnabledAsync(true); + _channelGroup.SetEnabledAsync(false); foreach (var channelMock in channelMocks.Select(mock => mock as Mock)) { - channelMock.Verify(channel => channel.SetEnabled(It.Is(p => p)), Times.Once()); - channelMock.Verify(channel => channel.SetEnabled(It.Is(p => !p)), Times.Once()); + channelMock.Verify(channel => channel.SetEnabledAsync(It.Is(p => p)), Times.Once()); + channelMock.Verify(channel => channel.SetEnabledAsync(It.Is(p => !p)), Times.Once()); } } @@ -162,7 +162,7 @@ public void TestEnableChannelGroup() public void TestDisposeChannelGroup() { _channelGroup.Dispose(); - Assert.ThrowsException(() => _channelGroup.SetEnabled(true)); + Assert.ThrowsException(() => _channelGroup.SetEnabledAsync(true)); } /// @@ -175,7 +175,7 @@ public void TestShutdownChannelGroup() var addedChannel = _channelGroup.AddChannel(channelName, 2, TimeSpan.FromSeconds(3), 3) as Mobile.Channel.Channel; - _channelGroup.Shutdown(); + _channelGroup.ShutdownAsync(); Assert.IsFalse(addedChannel.IsEnabled); } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs index f654429a1..9d83f6354 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs @@ -57,7 +57,7 @@ public void ChannelEnabledByDefault() [TestMethod] public void DisableChannel() { - _channel.SetEnabled(false); + _channel.SetEnabledAsync(false); Assert.IsFalse(_channel.IsEnabled); } @@ -68,8 +68,8 @@ public void DisableChannel() [TestMethod] public void EnableChannel() { - _channel.SetEnabled(false); - _channel.SetEnabled(true); + _channel.SetEnabledAsync(false); + _channel.SetEnabledAsync(true); Assert.IsTrue(_channel.IsEnabled); } @@ -88,7 +88,7 @@ public void EnqueuedLogsAreSame() sem.Release(); }; - _channel.Enqueue(log); + _channel.EnqueueAsync(log).RunNotAsync(); Assert.IsTrue(sem.Wait(DefaultWaitTime)); } @@ -101,7 +101,7 @@ public void EnqueueMaxLogs() SetChannelWithTimeSpan(TimeSpan.FromHours(1)); for (var i = 0; i < MaxLogsPerBatch; ++i) { - _channel.Enqueue(new TestLog()); + _channel.EnqueueAsync(new TestLog()).RunNotAsync(); } Assert.IsTrue(SendingLogOccurred(1)); } @@ -112,9 +112,9 @@ public void EnqueueMaxLogs() [TestMethod] public void EnqueueWhileDisabled() { - _channel.SetEnabled(false); + _channel.SetEnabledAsync(false).RunNotAsync(); var log = new TestLog(); - _channel.Enqueue(log); + _channel.EnqueueAsync(log).RunNotAsync(); Assert.IsFalse(SentLogOccurred(1)); } @@ -123,7 +123,7 @@ public void ChannelInvokesSendingLogEvent() { for (var i = 0; i < MaxLogsPerBatch; ++i) { - _channel.Enqueue(new TestLog()); + _channel.EnqueueAsync(new TestLog()).RunNotAsync(); } Assert.IsTrue(SendingLogOccurred(MaxLogsPerBatch)); @@ -134,7 +134,7 @@ public void ChannelInvokesSentLogEvent() { for (var i = 0; i < MaxLogsPerBatch; ++i) { - _channel.Enqueue(new TestLog()); + _channel.EnqueueAsync(new TestLog()).RunNotAsync(); } Assert.IsTrue(SentLogOccurred(MaxLogsPerBatch)); @@ -146,7 +146,7 @@ public void ChannelInvokesFailedToSendLogEvent() MakeIngestionCallsFail(); for (var i = 0; i < MaxLogsPerBatch; ++i) { - _channel.Enqueue(new TestLog()); + _channel.EnqueueAsync(new TestLog()).RunNotAsync(); } Assert.IsTrue(FailedToSendLogOccurred(MaxLogsPerBatch)); @@ -171,13 +171,13 @@ public void FailedToSendLogEventArgsAreSame() [TestMethod] public void ChannelInvokesSendingLogEventAfterEnabling() { - _channel.Shutdown().Wait(); + _channel.ShutdownAsync().RunNotAsync(); for (int i = 0; i < MaxLogsPerBatch; ++i) { - _channel.Enqueue(new TestLog())?.Wait(); + _channel.EnqueueAsync(new TestLog()).RunNotAsync(); } - _channel.SetEnabled(true); + _channel.SetEnabledAsync(true).RunNotAsync(); Assert.IsTrue(SendingLogOccurred(MaxLogsPerBatch)); } @@ -185,13 +185,13 @@ public void ChannelInvokesSendingLogEventAfterEnabling() /// /// Validate that FailedToSendLog calls when channel is disabled /// - [TestMethod] + [TestMethod] public void ChannelInvokesFailedToSendLogEventAfterDisabling() { - _channel.SetEnabled(false); + _channel.SetEnabledAsync(false).RunNotAsync(); for (int i = 0; i < MaxLogsPerBatch; ++i) { - _channel.Enqueue(new TestLog()); + _channel.EnqueueAsync(new TestLog()).RunNotAsync(); } Assert.IsTrue(SendingLogOccurred(MaxLogsPerBatch)); @@ -204,13 +204,11 @@ public void ChannelInvokesFailedToSendLogEventAfterDisabling() [TestMethod] public void ClearLogs() { - _channel.Shutdown().Wait(); - _channel.Enqueue(new TestLog()); - - Task.Delay(DefaultWaitTime).Wait(); + _channel.ShutdownAsync().RunNotAsync(); + _channel.EnqueueAsync(new TestLog()).RunNotAsync(); - _channel.Clear(); - _channel.SetEnabled(true); + _channel.ClearAsync().RunNotAsync(); + _channel.SetEnabledAsync(true).RunNotAsync(); Assert.IsFalse(SendingLogOccurred(1)); } @@ -222,7 +220,7 @@ public void ClearLogs() public void DisposeChannelTest() { _channel.Dispose(); - Assert.ThrowsException(() => _channel.SetEnabled(true)); + Assert.ThrowsExceptionAsync(() => _channel.SetEnabledAsync(true)); } /// @@ -238,20 +236,17 @@ public void ThrowStorageExceptionInDeleteLogsTime() Mobile.Channel.Channel channel = new Mobile.Channel.Channel("name", 1, _batchTimeSpan, 1, _appSecret, _mockIngestion, storage.Object); //Shutdown channel and store some log - channel.Shutdown(); - channel.Enqueue(new TestLog()); - - //Wait while log is saving - Task.Delay(1000).Wait(); + channel.ShutdownAsync().RunNotAsync(); + channel.EnqueueAsync(new TestLog()).RunNotAsync(); - channel.SetEnabled(true); + channel.SetEnabledAsync(true).RunNotAsync(); // Not throw any exception } private void SetChannelWithTimeSpan(TimeSpan timeSpan) { - _storage.DeleteLogsAsync(ChannelName).Wait(); + _storage.DeleteLogsAsync(ChannelName).RunNotAsync(); _channel = new Mobile.Channel.Channel(ChannelName, MaxLogsPerBatch, timeSpan, MaxParallelBatches, _appSecret, _mockIngestion, _storage); MakeIngestionCallsSucceed(); diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Http/RetryableTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Http/RetryableTest.cs index c891399f0..9a39abad1 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Http/RetryableTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Http/RetryableTest.cs @@ -19,13 +19,6 @@ public class RetryableTest private Mock _adapter; private IIngestion _retryableIngestion; - private const int DefaultWaitTime = 5000; - - /* Event semaphores for invokation verification */ - private const int SucceededCallbackSemaphoreIdx = 0; - private const int FailedCallbackSemaphoreIdx = 1; - private readonly List _eventSemaphores = new List { new SemaphoreSlim(0), new SemaphoreSlim(0) }; - [TestInitialize] public void InitializeRetryableTest() { @@ -167,12 +160,9 @@ public void ServiceCallSuccessCallbackTest() { SetupAdapterSendResponse(new HttpResponseMessage(HttpStatusCode.OK)); var call = PrepareServiceCall(); + call.ExecuteAsync().RunNotAsync(); - SetupEventCallbacks(call); - - call.Execute(); - - Assert.IsTrue(SuccessCallbackOccurred()); + // No throw any exception } [TestMethod] @@ -180,12 +170,7 @@ public void ServiceCallFailedCallbackTest() { SetupAdapterSendResponse(new HttpResponseMessage(HttpStatusCode.NotFound)); var call = PrepareServiceCall(); - - SetupEventCallbacks(call); - - call.Execute(); - - Assert.IsTrue(FailedCallbackOccurred()); + Assert.ThrowsException(() => { call.ExecuteAsync().RunNotAsync(); }); } /// @@ -259,41 +244,7 @@ public class TestInterval public Task Wait() { OnRequest?.Invoke(); return _task.Task; } public void Set() => _task.TrySetResult(true); } - - private void SetupEventCallbacks(IServiceCall call) - { - foreach (var sem in _eventSemaphores) - { - if (sem.CurrentCount != 0) - { - sem.Release(sem.CurrentCount); - } - } - - call.ServiceCallSucceededCallback += () => _eventSemaphores[SucceededCallbackSemaphoreIdx].Release(); - call.ServiceCallFailedCallback += (e) => _eventSemaphores[FailedCallbackSemaphoreIdx].Release(); - } - - private bool SuccessCallbackOccurred(int waitTime = DefaultWaitTime) - { - return EventWithSemaphoreOccurred(_eventSemaphores[SucceededCallbackSemaphoreIdx], 1, waitTime); - } - - private bool FailedCallbackOccurred(int waitTime = DefaultWaitTime) - { - return EventWithSemaphoreOccurred(_eventSemaphores[FailedCallbackSemaphoreIdx], 1, waitTime); - } - - private static bool EventWithSemaphoreOccurred(SemaphoreSlim semaphore, int numTimes, int waitTime) - { - var enteredAll = true; - for (var i = 0; i < numTimes; ++i) - { - enteredAll &= semaphore.Wait(waitTime); - } - return enteredAll; - } - + public class TestServiceCall : ServiceCallDecorator { public TestServiceCall(IServiceCall decoratedApi) : base(decoratedApi) diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Http/ServiceCallTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Http/ServiceCallTest.cs index 0749416f9..49793d6a3 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Http/ServiceCallTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Http/ServiceCallTest.cs @@ -1,8 +1,7 @@ -using Microsoft.Azure.Mobile.Ingestion.Http; +using System; +using Microsoft.Azure.Mobile.Ingestion.Http; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Collections.Generic; -using System.Threading; +using Microsoft.Azure.Mobile.Ingestion; namespace Microsoft.Azure.Mobile.Test.Windows.Ingestion.Http { @@ -12,19 +11,11 @@ public class ServiceCallTest private MockIngestion _ingestion; private ServiceCall _serviceCall; - private const int DefaultWaitTime = 5000; - - /* Event semaphores for invokation verification */ - private const int SucceededCallbackSemaphoreIdx = 0; - private const int FailedCallbackSemaphoreIdx = 1; - private readonly List _eventSemaphores = new List { new SemaphoreSlim(0), new SemaphoreSlim(0) }; - [TestInitialize] public void InitializeServiceCallTest() { _ingestion = new MockIngestion(); _serviceCall = new MockServiceCall(_ingestion, null, string.Empty, Guid.NewGuid()); - SetupEventCallbacks(); } [TestMethod] @@ -32,53 +23,14 @@ public void CheckSuccessCallback() { _ingestion.CallShouldSucceed = true; - _serviceCall.Execute(); - - Assert.IsTrue(SuccessCallbackOccurred()); + _serviceCall.ExecuteAsync().RunNotAsync(); } [TestMethod] public void CheckUnsuccessCallback() { _ingestion.CallShouldSucceed = false; - - _serviceCall.Execute(); - - Assert.IsTrue(FailedCallbackOccurred()); - } - - private void SetupEventCallbacks() - { - foreach (var sem in _eventSemaphores) - { - if (sem.CurrentCount != 0) - { - sem.Release(sem.CurrentCount); - } - } - - _serviceCall.ServiceCallSucceededCallback += () => _eventSemaphores[SucceededCallbackSemaphoreIdx].Release(); - _serviceCall.ServiceCallFailedCallback += (e) => _eventSemaphores[FailedCallbackSemaphoreIdx].Release(); - } - - private bool SuccessCallbackOccurred(int waitTime = DefaultWaitTime) - { - return EventWithSemaphoreOccurred(_eventSemaphores[SucceededCallbackSemaphoreIdx], 1, waitTime); - } - - private bool FailedCallbackOccurred(int waitTime = DefaultWaitTime) - { - return EventWithSemaphoreOccurred(_eventSemaphores[FailedCallbackSemaphoreIdx], 1, waitTime); - } - - private static bool EventWithSemaphoreOccurred(SemaphoreSlim semaphore, int numTimes, int waitTime) - { - var enteredAll = true; - for (var i = 0; i < numTimes; ++i) - { - enteredAll &= semaphore.Wait(waitTime); - } - return enteredAll; + Assert.ThrowsException(() => _serviceCall.ExecuteAsync().RunNotAsync()); } } } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterServiceTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterServiceTest.cs index 8cd76765d..a92888961 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterServiceTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterServiceTest.cs @@ -101,7 +101,7 @@ public void SetEnabledDifferentValue() _testService.InstanceEnabled = false; _mockSettings.VerifySet(settings => settings[_testService.PublicEnabledPreferenceKey] = It.IsAny(), Times.Exactly(2)); - _mockChannel.Verify(channel => channel.SetEnabled(It.IsAny()), Times.Exactly(2)); + _mockChannel.Verify(channel => channel.SetEnabledAsync(It.IsAny()), Times.Exactly(2)); } /// @@ -120,7 +120,7 @@ public void OnChannelGroupReady() channelGroup.AddChannel(_testService.PublicChannelName, It.IsAny(), It.IsAny(), It.IsAny()), Times.Once()); _mockSettings.VerifySet(settings => settings[_testService.PublicEnabledPreferenceKey] = true, Times.Once()); - _mockChannel.Verify(channel => channel.SetEnabled(true), Times.Once()); + _mockChannel.Verify(channel => channel.SetEnabledAsync(true), Times.Once()); Assert.AreSame(_mockChannelGroup.Object, _testService.PublicChannelGroup); } @@ -141,7 +141,7 @@ public void OnChannelGroupReadyMobileCenterIsDisabled() channelGroup.AddChannel(_testService.PublicChannelName, It.IsAny(), It.IsAny(), It.IsAny()), Times.Once()); _mockSettings.VerifySet(settings => settings[_testService.PublicEnabledPreferenceKey] = false, Times.Once()); - _mockChannel.Verify(channel => channel.SetEnabled(false), Times.Once()); + _mockChannel.Verify(channel => channel.SetEnabledAsync(false), Times.Once()); } /// diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs index 66559e5e4..2ac110548 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs @@ -144,7 +144,7 @@ public void SetEnabledSameValue() MockMobileCenterService.Instance.MockInstance.VerifySet( service => service.InstanceEnabled = It.IsAny(), Times.Never()); settingsMock.VerifySet(settings => settings[MobileCenter.EnabledKey] = It.IsAny(), Times.Never()); - channelGroupMock.Verify(channelGroup => channelGroup.SetEnabled(It.IsAny()), Times.Never()); + channelGroupMock.Verify(channelGroup => channelGroup.SetEnabledAsync(It.IsAny()), Times.Never()); } /// @@ -166,7 +166,7 @@ public void SetEnabledDifferentValueAfterConfigure() MockMobileCenterService.Instance.MockInstance.VerifySet(service => service.InstanceEnabled = setVal, Times.Once()); settingsMock.VerifySet(settings => settings[MobileCenter.EnabledKey] = setVal, Times.Once()); - channelGroupMock.Verify(channelGroup => channelGroup.SetEnabled(setVal), Times.Once()); + channelGroupMock.Verify(channelGroup => channelGroup.SetEnabledAsync(setVal), Times.Once()); } /// @@ -500,18 +500,18 @@ public void SetCustomProperties() /* Set null. */ MobileCenter.SetCustomProperties(null); - channelUnitMock.Verify(channel => channel.Enqueue(It.IsAny()), Times.Never()); + channelUnitMock.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); /* Set empty. */ var empty = new CustomProperties(); MobileCenter.SetCustomProperties(empty); - channelUnitMock.Verify(channel => channel.Enqueue(It.IsAny()), Times.Never()); + channelUnitMock.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); /* Set normal. */ var properties = new CustomProperties(); properties.Set("test", "test"); MobileCenter.SetCustomProperties(properties); - channelUnitMock.Verify(channel => channel.Enqueue(It.Is(log => + channelUnitMock.Verify(channel => channel.EnqueueAsync(It.Is(log => log.Properties == properties.Properties)), Times.Once()); } } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs index 52ca225bf..f214166bb 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs @@ -1,5 +1,4 @@ using System; -using System.Data.Common; using System.Collections.Generic; using System.Linq.Expressions; using System.Threading.Tasks; @@ -43,7 +42,7 @@ public void ShutdownTimeout() countdownEvent.Wait(); Task.Delay(100).Wait(); - var result = storage.Shutdown(TimeSpan.FromTicks(1)); + var result = storage.ShutdownAsync(TimeSpan.FromTicks(1)).RunNotAsync(); Assert.IsFalse(result); } @@ -62,7 +61,7 @@ public void ShutdownSucceed() var storage = new Mobile.Storage.Storage(mockConnection.Object); Task.Run(() => storage.PutLogAsync(StorageTestChannelName, new TestLog())); Task.Run(() => storage.PutLogAsync(StorageTestChannelName, new TestLog())); - var result = storage.Shutdown(TimeSpan.FromSeconds(100)); + var result = storage.ShutdownAsync(TimeSpan.FromSeconds(100)).RunNotAsync(); Assert.IsTrue(result); } @@ -74,7 +73,8 @@ public void ShutdownPreventsNewTasks() { var mockConnection = new Mock(); var storage = new Mobile.Storage.Storage(mockConnection.Object); - Assert.IsTrue(storage.Shutdown(TimeSpan.FromSeconds(10))); + var result = storage.ShutdownAsync(TimeSpan.FromSeconds(10)).RunNotAsync(); + Assert.IsTrue(result); Assert.ThrowsException( () => storage.GetLogsAsync(It.IsAny(), It.IsAny(), It.IsAny>()).RunNotAsync()); } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/MockStorage.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/MockStorage.cs index 6fbd19413..8160bb748 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/MockStorage.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/MockStorage.cs @@ -38,9 +38,9 @@ public Task PutLogAsync(string channelName, Log log) return TaskExtension.GetCompletedTask(); } - public bool Shutdown(TimeSpan timeout) + public Task ShutdownAsync(TimeSpan timeout) { - return true; + return TaskExtension.GetCompletedTask(true); } public void Dispose() diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/StorageTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/StorageTest.cs index c771f7fa8..930d2989c 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/StorageTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/StorageTest.cs @@ -1,8 +1,6 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Threading.Tasks; using Microsoft.Azure.Mobile.Ingestion.Models; -using Microsoft.Azure.Mobile.Storage; using Microsoft.VisualStudio.TestTools.UnitTesting; using SQLite; From dd7a5eeae56e377578f0f9d982da0686823bf74c Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Mon, 22 May 2017 20:58:33 +0300 Subject: [PATCH 10/90] Fix remarks --- .../Channel/Channel.cs | 116 +++++++++--------- .../Ingestion/Http/RetryableServiceCall.cs | 4 +- 2 files changed, 57 insertions(+), 63 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs index 6474d1530..349413c24 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs @@ -43,7 +43,6 @@ internal Channel(string name, int maxLogsPerBatch, TimeSpan batchTimeInterval, i _batchScheduled = false; _enabled = true; DeviceInformationHelper.InformationInvalidated += (sender, e) => InvalidateDeviceCache(); - Task.Run(CountFromDiskAsync); } public async Task SetEnabledAsync(bool enabled) @@ -61,15 +60,15 @@ public async Task SetEnabledAsync(bool enabled) _discardLogs = false; _stateKeeper.InvalidateState(); var stateSnapshot = _stateKeeper.GetStateSnapshot(); - - // We need count logs from storage here because CountFromDiskAsync may be aborted. + _mutex.Unlock(); var logCount = await _storage.CountLogsAsync(Name).ConfigureAwait(false); + await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); _pendingLogCount = logCount; - await CheckPendingLogs(stateSnapshot).ConfigureAwait(false); + await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); } else { - await Suspend(true, new CancellationException()).ConfigureAwait(false); + await SuspendAsync(true, new CancellationException()).ConfigureAwait(false); } } finally @@ -124,11 +123,8 @@ public async Task EnqueueAsync(Log log) } _mutex.Unlock(); EnqueuingLog?.Invoke(this, new EnqueuingLogEventArgs(log)); - await Task.Run(async () => - { - await PrepareLogAsync(log).ConfigureAwait(false); - await PersistLogAsync(log, stateSnapshot).ConfigureAwait(false); - }).ConfigureAwait(false); + await PrepareLogAsync(log, stateSnapshot).ConfigureAwait(false); + await PersistLogAsync(log, stateSnapshot).ConfigureAwait(false); } catch (StatefulMutexException e) { @@ -136,11 +132,20 @@ await Task.Run(async () => } } - private async Task PrepareLogAsync(Log log) + private async Task PrepareLogAsync(Log log, State stateSnapshot) { if (log.Device == null && _device == null) { - _device = await _deviceInfoHelper.GetDeviceInformationAsync().ConfigureAwait(false); + var device = await _deviceInfoHelper.GetDeviceInformationAsync().ConfigureAwait(false); + try + { + await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); + _device = device; + } + finally + { + _mutex.Unlock(); + } } log.Device = log.Device ?? _device; if (log.Toffset == 0L) @@ -166,7 +171,7 @@ private async Task PersistLogAsync(Log log, State stateSnapshot) _pendingLogCount++; if (_enabled) { - await CheckPendingLogs(stateSnapshot).ConfigureAwait(false); + await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); return; } MobileCenterLog.Warn(MobileCenterLog.LogTag, "Channel is temporarily disabled; log was saved to disk"); @@ -190,11 +195,11 @@ public void InvalidateDeviceCache() public async Task ClearAsync() { - await _mutex.LockAsync().ConfigureAwait(false); var stateSnapshot = _stateKeeper.GetStateSnapshot(); + await _storage.DeleteLogsAsync(Name).ConfigureAwait(false); try { - await _storage.DeleteLogsAsync(Name).ConfigureAwait(false); + await _mutex.LockAsync().ConfigureAwait(false); _pendingLogCount = 0; } catch (StatefulMutexException e) @@ -207,31 +212,7 @@ public async Task ClearAsync() } } - private async Task CountFromDiskAsync() - { - try - { - await _mutex.LockAsync().ConfigureAwait(false); - var stateSnapshot = _stateKeeper.GetStateSnapshot(); - _mutex.Unlock(); - var logCount = await _storage.CountLogsAsync(Name).ConfigureAwait(false); - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); - _pendingLogCount = logCount; - await CheckPendingLogs(stateSnapshot).ConfigureAwait(false); - } - catch (StatefulMutexException) - { - // The CountFromDisk operation has been cancelled. - // This may happen when we call Shutdown right after constructor. - // We will call CountLogs when channel will be enabled again. - } - finally - { - _mutex.Unlock(); - } - } - - private async Task Suspend(bool deleteLogs, Exception exception) + private async Task SuspendAsync(bool deleteLogs, Exception exception) { _enabled = false; _batchScheduled = false; @@ -246,7 +227,7 @@ private async Task Suspend(bool deleteLogs, Exception exception) { _mutex.Unlock(); FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, exception)); - _mutex.Lock(stateSnapshot); + await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); } } try @@ -260,10 +241,14 @@ private async Task Suspend(bool deleteLogs, Exception exception) if (deleteLogs) { _pendingLogCount = 0; - await DeleteLogsOnSuspendedAsync(stateSnapshot).ConfigureAwait(false); + _mutex.Unlock(); + await DeleteLogsOnSuspendedAsync().ConfigureAwait(false); + await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); return; } + _mutex.Unlock(); await _storage.ClearPendingLogStateAsync(Name).ConfigureAwait(false); + await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); } catch (StatefulMutexException e) { @@ -271,13 +256,13 @@ private async Task Suspend(bool deleteLogs, Exception exception) } } - private async Task DeleteLogsOnSuspendedAsync(State stateSnapshot) + private async Task DeleteLogsOnSuspendedAsync() { try { if (SendingLog != null || FailedToSendLog != null) { - await SignalDeletingLogs(stateSnapshot).ConfigureAwait(false); + await SignalDeletingLogsAsync().ConfigureAwait(false); } } catch (StorageException) @@ -288,22 +273,18 @@ private async Task DeleteLogsOnSuspendedAsync(State stateSnapshot) await _storage.DeleteLogsAsync(Name).ConfigureAwait(false); } - private async Task SignalDeletingLogs(State stateSnapshot) + private async Task SignalDeletingLogsAsync() { var logs = new List(); - _mutex.Unlock(); await _storage.GetLogsAsync(Name, ClearBatchSize, logs).ConfigureAwait(false); - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); foreach (var log in logs) { - _mutex.Unlock(); SendingLog?.Invoke(this, new SendingLogEventArgs(log)); FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, new CancellationException())); - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); } if (logs.Count >= ClearBatchSize) { - await SignalDeletingLogs(stateSnapshot).ConfigureAwait(false); + await SignalDeletingLogsAsync().ConfigureAwait(false); } } @@ -332,12 +313,12 @@ private async Task TriggerIngestionAsync(State stateSnapshot) { _sendingBatches.Add(batchId, logs); _pendingLogCount -= logs.Count; - await TriggerIngestion(logs, stateSnapshot, batchId).ConfigureAwait(false); - await CheckPendingLogs(stateSnapshot).ConfigureAwait(false); + await TriggerIngestionAsync(logs, stateSnapshot, batchId).ConfigureAwait(false); + await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); } } - private async Task TriggerIngestion(IList logs, State stateSnapshot, string batchId) + private async Task TriggerIngestionAsync(IList logs, State stateSnapshot, string batchId) { // Before sending logs, trigger the sending event for this channel if (SendingLog != null) @@ -346,7 +327,7 @@ private async Task TriggerIngestion(IList logs, State stateSnapshot, string { _mutex.Unlock(); SendingLog?.Invoke(this, eventArgs); - _mutex.Lock(stateSnapshot); + await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); } } // If the optional Install ID has no value, default to using empty GUID @@ -355,11 +336,19 @@ private async Task TriggerIngestion(IList logs, State stateSnapshot, string { try { - await serviceCall.ExecuteAsync().ConfigureAwait(false); + _mutex.Unlock(); + try + { + await serviceCall.ExecuteAsync().ConfigureAwait(false); + } + finally + { + await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); + } } catch (IngestionException exception) { - HandleSendingFailure(batchId, exception); + await HandleSendingFailureAsync(batchId, exception).ConfigureAwait(false); return; } } @@ -369,12 +358,17 @@ private async Task TriggerIngestion(IList logs, State stateSnapshot, string } try { + _mutex.Unlock(); await _storage.DeleteLogsAsync(Name, batchId).ConfigureAwait(false); } catch (StorageException e) { MobileCenterLog.Warn(MobileCenterLog.LogTag, $"Could not delete logs for batch {batchId}", e); } + finally + { + await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); + } var removedLogs = _sendingBatches[batchId]; _sendingBatches.Remove(batchId); if (SentLog != null) @@ -383,12 +377,12 @@ private async Task TriggerIngestion(IList logs, State stateSnapshot, string { _mutex.Unlock(); SentLog?.Invoke(this, new SentLogEventArgs(log)); - _mutex.Lock(stateSnapshot); + await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); } } } - private void HandleSendingFailure(string batchId, IngestionException e) + private async Task HandleSendingFailureAsync(string batchId, IngestionException e) { var isRecoverable = e?.IsRecoverable ?? false; MobileCenterLog.Error(MobileCenterLog.LogTag, $"Sending logs for channel '{Name}', batch '{batchId}' failed", e); @@ -401,14 +395,14 @@ private void HandleSendingFailure(string batchId, IngestionException e) FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, e)); } } - Suspend(!isRecoverable, e); + await SuspendAsync(!isRecoverable, e).ConfigureAwait(false); if (isRecoverable) { _pendingLogCount += removedLogs.Count; } } - private async Task CheckPendingLogs(State stateSnapshot) + private async Task CheckPendingLogsAsync(State stateSnapshot) { if (!_enabled) { @@ -455,7 +449,7 @@ public async Task ShutdownAsync() await _mutex.LockAsync().ConfigureAwait(false); try { - await Suspend(false, new CancellationException()).ConfigureAwait(false); + await SuspendAsync(false, new CancellationException()).ConfigureAwait(false); } finally { diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableServiceCall.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableServiceCall.cs index 3f54827a5..387e8bfa9 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableServiceCall.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/RetryableServiceCall.cs @@ -19,7 +19,7 @@ public RetryableServiceCall(IServiceCall decoratedApi, Func[] retryInterva } /// - private async Task RunWithRetriesAsyncHelper() + private async Task ExecuteAsyncHelper() { while (true) { @@ -52,7 +52,7 @@ public override async Task ExecuteAsync() try { _tokenSource = new CancellationTokenSource(); - await RunWithRetriesAsyncHelper().ConfigureAwait(false); + await ExecuteAsyncHelper().ConfigureAwait(false); } finally { From 464ac2f8d1b3cedad213bad2ece84d2438704d1b Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Tue, 23 May 2017 00:47:34 +0300 Subject: [PATCH 11/90] Add LockHolder for StatefulMutex --- .../Channel/Channel.cs | 295 ++++++++---------- ...soft.Azure.Mobile.Windows.Shared.projitems | 3 - .../MobileCenter.cs | 1 + .../Storage/Storage.cs | 23 +- .../Storage/TaskLock.cs | 22 -- .../Storage/TaskLockSource.cs | 84 ----- .../Utils/Synchronization/StateKeeper.cs | 38 --- .../Utils/Synchronization/StatefulMutex.cs | 117 +++++-- .../Microsoft.Azure.Mobile.Push.UWP/Push.cs | 45 ++- .../Push.cs | 21 +- .../Channel/ChannelTest.cs | 4 +- .../Channel/MockChannelGroupFactory.cs | 2 +- .../MobileCenterTest.cs | 12 + .../Storage/FakeStorageTest.cs | 7 +- 14 files changed, 286 insertions(+), 388 deletions(-) delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLock.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StateKeeper.cs diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs index 349413c24..82db49247 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs @@ -26,13 +26,11 @@ public sealed class Channel : IChannelUnit private bool _discardLogs; private bool _batchScheduled; private TimeSpan _batchTimeInterval; - private readonly StatefulMutex _mutex; - private readonly StateKeeper _stateKeeper = new StateKeeper(); + private readonly StatefulMutex _mutex = new StatefulMutex(); internal Channel(string name, int maxLogsPerBatch, TimeSpan batchTimeInterval, int maxParallelBatches, string appSecret, IIngestion ingestion, IStorage storage) { - _mutex = new StatefulMutex(_stateKeeper); Name = name; _maxParallelBatches = maxParallelBatches; _maxLogsPerBatch = maxLogsPerBatch; @@ -47,33 +45,22 @@ internal Channel(string name, int maxLogsPerBatch, TimeSpan batchTimeInterval, i public async Task SetEnabledAsync(bool enabled) { - await _mutex.LockAsync().ConfigureAwait(false); - try + State state; + using (await _mutex.GetLockAsync().ConfigureAwait(false)) { if (_enabled == enabled) { return; } - if (enabled) - { - _enabled = true; - _discardLogs = false; - _stateKeeper.InvalidateState(); - var stateSnapshot = _stateKeeper.GetStateSnapshot(); - _mutex.Unlock(); - var logCount = await _storage.CountLogsAsync(Name).ConfigureAwait(false); - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); - _pendingLogCount = logCount; - await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); - } - else - { - await SuspendAsync(true, new CancellationException()).ConfigureAwait(false); - } + state = _mutex.State; + } + if (enabled) + { + await ResumeAsync(state).ConfigureAwait(false); } - finally + else { - _mutex.Unlock(); + await SuspendAsync(state, true, new CancellationException()).ConfigureAwait(false); } } @@ -84,15 +71,10 @@ public bool IsEnabled { get { - _mutex.Lock(); - try + using (_mutex.GetLock()) { return _enabled; } - finally - { - _mutex.Unlock(); - } } } @@ -112,19 +94,22 @@ public async Task EnqueueAsync(Log log) { try { - await _mutex.LockAsync().ConfigureAwait(false); - var stateSnapshot = _stateKeeper.GetStateSnapshot(); - if (_discardLogs) + State state; + bool discardLogs; + using (await _mutex.GetLockAsync().ConfigureAwait(false)) + { + state = _mutex.State; + discardLogs = _discardLogs; + } + if (discardLogs) { MobileCenterLog.Warn(MobileCenterLog.LogTag, "Channel is disabled; logs are discarded"); - _mutex.Unlock(); SendingLog?.Invoke(this, new SendingLogEventArgs(log)); FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, new CancellationException())); } - _mutex.Unlock(); EnqueuingLog?.Invoke(this, new EnqueuingLogEventArgs(log)); - await PrepareLogAsync(log, stateSnapshot).ConfigureAwait(false); - await PersistLogAsync(log, stateSnapshot).ConfigureAwait(false); + await PrepareLogAsync(log, state).ConfigureAwait(false); + await PersistLogAsync(log, state).ConfigureAwait(false); } catch (StatefulMutexException e) { @@ -132,20 +117,15 @@ public async Task EnqueueAsync(Log log) } } - private async Task PrepareLogAsync(Log log, State stateSnapshot) + private async Task PrepareLogAsync(Log log, State state) { if (log.Device == null && _device == null) { var device = await _deviceInfoHelper.GetDeviceInformationAsync().ConfigureAwait(false); - try + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) { - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); _device = device; } - finally - { - _mutex.Unlock(); - } } log.Device = log.Device ?? _device; if (log.Toffset == 0L) @@ -154,7 +134,7 @@ private async Task PrepareLogAsync(Log log, State stateSnapshot) } } - private async Task PersistLogAsync(Log log, State stateSnapshot) + private async Task PersistLogAsync(Log log, State state) { try { @@ -167,11 +147,15 @@ private async Task PersistLogAsync(Log log, State stateSnapshot) } try { - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); - _pendingLogCount++; - if (_enabled) + bool enabled; + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) + { + _pendingLogCount++; + enabled = _enabled; + } + if (enabled) { - await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); + await CheckPendingLogsAsync(state).ConfigureAwait(false); return; } MobileCenterLog.Warn(MobileCenterLog.LogTag, "Channel is temporarily disabled; log was saved to disk"); @@ -180,80 +164,89 @@ private async Task PersistLogAsync(Log log, State stateSnapshot) { MobileCenterLog.Warn(MobileCenterLog.LogTag, "The PersistLog operation has been cancelled", e); } - finally - { - _mutex.Unlock(); - } } public void InvalidateDeviceCache() { - _mutex.Lock(); - _device = null; - _mutex.Unlock(); + using (_mutex.GetLock()) + { + _device = null; + } } public async Task ClearAsync() { - var stateSnapshot = _stateKeeper.GetStateSnapshot(); + var state = _mutex.State; await _storage.DeleteLogsAsync(Name).ConfigureAwait(false); try { - await _mutex.LockAsync().ConfigureAwait(false); - _pendingLogCount = 0; + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) + { + _pendingLogCount = 0; + } } catch (StatefulMutexException e) { MobileCenterLog.Warn(MobileCenterLog.LogTag, "The Clear operation has been cancelled", e); } - finally - { - _mutex.Unlock(); - } } - private async Task SuspendAsync(bool deleteLogs, Exception exception) + private async Task ResumeAsync(State state) { - _enabled = false; - _batchScheduled = false; - _discardLogs = deleteLogs; - _stateKeeper.InvalidateState(); - var stateSnapshot = _stateKeeper.GetStateSnapshot(); try { - if (deleteLogs && FailedToSendLog != null) + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) { - foreach (var log in _sendingBatches.Values.SelectMany(batch => batch)) - { - _mutex.Unlock(); - FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, exception)); - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); - } + _enabled = true; + _discardLogs = false; + _mutex.InvalidateState(); + state = _mutex.State; } - try + var logCount = await _storage.CountLogsAsync(Name).ConfigureAwait(false); + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) { - _ingestion.Close(); + _pendingLogCount = logCount; } - catch (IngestionException e) + } + catch (StatefulMutexException e) + { + MobileCenterLog.Warn(MobileCenterLog.LogTag, "The Resume operation has been cancelled", e); + } + await CheckPendingLogsAsync(state).ConfigureAwait(false); + } + + private async Task SuspendAsync(State state, bool deleteLogs, Exception exception) + { + try + { + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) { - MobileCenterLog.Error(MobileCenterLog.LogTag, "Failed to close ingestion", e); + _enabled = false; + _batchScheduled = false; + _discardLogs = deleteLogs; + _mutex.InvalidateState(); } - if (deleteLogs) + } + catch (StatefulMutexException e) + { + MobileCenterLog.Warn(MobileCenterLog.LogTag, "The Suspend operation has been cancelled", e); + } + if (deleteLogs && FailedToSendLog != null) + { + foreach (var log in _sendingBatches.Values.SelectMany(batch => batch)) { - _pendingLogCount = 0; - _mutex.Unlock(); - await DeleteLogsOnSuspendedAsync().ConfigureAwait(false); - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); - return; + FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, exception)); } - _mutex.Unlock(); - await _storage.ClearPendingLogStateAsync(Name).ConfigureAwait(false); - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); } - catch (StatefulMutexException e) + try + { + _ingestion.Close(); + } + catch (IngestionException e) { - MobileCenterLog.Warn(MobileCenterLog.LogTag, "The CountFromDisk operation has been cancelled", e); + MobileCenterLog.Error(MobileCenterLog.LogTag, "Failed to close ingestion", e); } + await _storage.ClearPendingLogStateAsync(Name).ConfigureAwait(false); } private async Task DeleteLogsOnSuspendedAsync() @@ -288,106 +281,106 @@ private async Task SignalDeletingLogsAsync() } } - private async Task TriggerIngestionAsync(State stateSnapshot) + private async Task TriggerIngestionAsync(State state) { - if (!_enabled) - { - return; - } - MobileCenterLog.Debug(MobileCenterLog.LogTag, - $"triggerIngestion({Name}) pendingLogCount={_pendingLogCount}"); - _batchScheduled = false; - if (_sendingBatches.Count >= _maxParallelBatches) + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) { + if (!_enabled) + { + return; + } MobileCenterLog.Debug(MobileCenterLog.LogTag, - "Already sending " + _maxParallelBatches + " batches of analytics data to the server"); - return; + $"triggerIngestion({Name}) pendingLogCount={_pendingLogCount}"); + _batchScheduled = false; + if (_sendingBatches.Count >= _maxParallelBatches) + { + MobileCenterLog.Debug(MobileCenterLog.LogTag, + "Already sending " + _maxParallelBatches + " batches of analytics data to the server"); + return; + } } // Get a batch from storage var logs = new List(); - _mutex.Unlock(); var batchId = await _storage.GetLogsAsync(Name, _maxLogsPerBatch, logs).ConfigureAwait(false); - await _mutex.LockAsync(stateSnapshot).ConfigureAwait(false); if (batchId != null) { - _sendingBatches.Add(batchId, logs); - _pendingLogCount -= logs.Count; - await TriggerIngestionAsync(logs, stateSnapshot, batchId).ConfigureAwait(false); - await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) + { + _sendingBatches.Add(batchId, logs); + _pendingLogCount -= logs.Count; + } + await TriggerIngestionAsync(state, logs, batchId).ConfigureAwait(false); + await CheckPendingLogsAsync(state).ConfigureAwait(false); } } - private async Task TriggerIngestionAsync(IList logs, State stateSnapshot, string batchId) + private async Task TriggerIngestionAsync(State state, IList logs, string batchId) { // Before sending logs, trigger the sending event for this channel if (SendingLog != null) { foreach (var eventArgs in logs.Select(log => new SendingLogEventArgs(log))) { - _mutex.Unlock(); SendingLog?.Invoke(this, eventArgs); - await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); } } + // If the optional Install ID has no value, default to using empty GUID var installId = MobileCenter.InstallId.HasValue ? MobileCenter.InstallId.Value : Guid.Empty; using (var serviceCall = _ingestion.PrepareServiceCall(_appSecret, installId, logs)) { try { - _mutex.Unlock(); - try - { - await serviceCall.ExecuteAsync().ConfigureAwait(false); - } - finally - { - await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); - } + await serviceCall.ExecuteAsync().ConfigureAwait(false); } catch (IngestionException exception) { - await HandleSendingFailureAsync(batchId, exception).ConfigureAwait(false); + await HandleSendingFailureAsync(state, batchId, exception).ConfigureAwait(false); return; } } - if (!_stateKeeper.IsCurrent(stateSnapshot)) + if (!_mutex.IsCurrent(state)) { return; } try { - _mutex.Unlock(); await _storage.DeleteLogsAsync(Name, batchId).ConfigureAwait(false); } catch (StorageException e) { MobileCenterLog.Warn(MobileCenterLog.LogTag, $"Could not delete logs for batch {batchId}", e); } - finally + List removedLogs; + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) { - await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); + removedLogs = _sendingBatches[batchId]; + _sendingBatches.Remove(batchId); } - var removedLogs = _sendingBatches[batchId]; - _sendingBatches.Remove(batchId); if (SentLog != null) { foreach (var log in removedLogs) { - _mutex.Unlock(); SentLog?.Invoke(this, new SentLogEventArgs(log)); - await CheckPendingLogsAsync(stateSnapshot).ConfigureAwait(false); } } } - private async Task HandleSendingFailureAsync(string batchId, IngestionException e) + private async Task HandleSendingFailureAsync(State state, string batchId, IngestionException e) { var isRecoverable = e?.IsRecoverable ?? false; MobileCenterLog.Error(MobileCenterLog.LogTag, $"Sending logs for channel '{Name}', batch '{batchId}' failed", e); - var removedLogs = _sendingBatches[batchId]; - _sendingBatches.Remove(batchId); + List removedLogs; + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) + { + removedLogs = _sendingBatches[batchId]; + _sendingBatches.Remove(batchId); + if (isRecoverable) + { + _pendingLogCount += removedLogs.Count; + } + } if (!isRecoverable && FailedToSendLog != null) { foreach (var log in removedLogs) @@ -395,14 +388,10 @@ private async Task HandleSendingFailureAsync(string batchId, IngestionException FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, e)); } } - await SuspendAsync(!isRecoverable, e).ConfigureAwait(false); - if (isRecoverable) - { - _pendingLogCount += removedLogs.Count; - } + await SuspendAsync(state, !isRecoverable, e).ConfigureAwait(false); } - private async Task CheckPendingLogsAsync(State stateSnapshot) + private async Task CheckPendingLogsAsync(State state) { if (!_enabled) { @@ -412,49 +401,29 @@ private async Task CheckPendingLogsAsync(State stateSnapshot) MobileCenterLog.Debug(MobileCenterLog.LogTag, $"CheckPendingLogs({Name}) pending log count: {_pendingLogCount}"); if (_pendingLogCount >= _maxLogsPerBatch) { - await TriggerIngestionAsync(stateSnapshot).ConfigureAwait(false); + await TriggerIngestionAsync(state).ConfigureAwait(false); } else if (_pendingLogCount > 0 && !_batchScheduled) { _batchScheduled = true; // No need wait _batchTimeInterval here. -#pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed +#pragma warning disable CS4014 Task.Run(async () => { await Task.Delay((int)_batchTimeInterval.TotalMilliseconds).ConfigureAwait(false); if (_batchScheduled) { - try - { - await _mutex.LockAsync().ConfigureAwait(false); - await TriggerIngestionAsync(_stateKeeper.GetStateSnapshot()).ConfigureAwait(false); - } - catch (StatefulMutexException e) - { - MobileCenterLog.Warn(MobileCenterLog.LogTag, "The TriggerIngestion operation has been cancelled", e); - } - finally - { - _mutex.Unlock(); - } + await TriggerIngestionAsync(_mutex.State).ConfigureAwait(false); } }); -#pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed +#pragma warning restore CS4014 } } - public async Task ShutdownAsync() + public Task ShutdownAsync() { - await _mutex.LockAsync().ConfigureAwait(false); - try - { - await SuspendAsync(false, new CancellationException()).ConfigureAwait(false); - } - finally - { - _mutex.Unlock(); - } + return SuspendAsync(_mutex.State, false, new CancellationException()); } public void Dispose() diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems index 527453615..419d12a32 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems @@ -24,8 +24,6 @@ - - @@ -62,7 +60,6 @@ - diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs index d9527a234..81cf5fc54 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs @@ -287,6 +287,7 @@ internal void InstanceConfigure(string appSecretOrSecrets) _applicationLifecycleHelper.UnhandledExceptionOccurred += (sender, e) => _channelGroup.ShutdownAsync(); _channel = _channelGroup.AddChannel(ChannelName, Constants.DefaultTriggerCount, Constants.DefaultTriggerInterval, Constants.DefaultTriggerMaxParallelRequests); + _channel.SetEnabledAsync(true); if (_logUrl != null) { _channelGroup.SetLogUrl(_logUrl); diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs index b168c2771..477f89d0b 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Newtonsoft.Json; using Microsoft.Azure.Mobile.Ingestion.Models; +using Microsoft.Azure.Mobile.Utils.Synchronization; using SQLite; namespace Microsoft.Azure.Mobile.Storage @@ -30,7 +31,7 @@ internal class LogEntry private readonly Dictionary> _pendingDbIdentifierGroups = new Dictionary>(); private readonly HashSet _pendingDbIdentifiers = new HashSet(); - private readonly TaskLock.TaskLockSource _taskLockSource = new TaskLock.TaskLockSource(); + private readonly StatefulMutex _mutex = new StatefulMutex(); /// /// Creates an instance of Storage @@ -45,8 +46,8 @@ public Storage() : this(new StorageAdapter(Database)) internal Storage(IStorageAdapter adapter) { _storageAdapter = adapter; - var taskLock = _taskLockSource.GetTaskLock(); - Task.Run(InitializeDatabaseAsync).ContinueWith(completedTask => taskLock.Dispose()); + _mutex.Lock(); + Task.Run(InitializeDatabaseAsync).ContinueWith(completedTask => _mutex.Unlock()); } /// @@ -57,7 +58,7 @@ internal Storage(IStorageAdapter adapter) /// public async Task PutLogAsync(string channelName, Log log) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + using (await _mutex.GetLockAsync().ConfigureAwait(false)) { var logJsonString = LogSerializer.Serialize(log); var logEntry = new LogEntry { Channel = channelName, Log = logJsonString }; @@ -73,7 +74,7 @@ public async Task PutLogAsync(string channelName, Log log) /// public async Task DeleteLogsAsync(string channelName, string batchId) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + using (await _mutex.GetLockAsync().ConfigureAwait(false)) { MobileCenterLog.Debug(MobileCenterLog.LogTag, $"Deleting logs from storage for channel '{channelName}' with batch id '{batchId}'"); @@ -107,7 +108,7 @@ public async Task DeleteLogsAsync(string channelName, string batchId) /// public async Task DeleteLogsAsync(string channelName) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + using (await _mutex.GetLockAsync().ConfigureAwait(false)) { MobileCenterLog.Debug(MobileCenterLog.LogTag, $"Deleting all logs from storage for channel '{channelName}'"); @@ -148,7 +149,7 @@ await _storageAdapter.DeleteAsync(entry => entry.Channel == channelNam /// public async Task CountLogsAsync(string channelName) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + using (await _mutex.GetLockAsync().ConfigureAwait(false)) { return await _storageAdapter.CountAsync(entry => entry.Channel == channelName) .ConfigureAwait(false); @@ -161,7 +162,7 @@ public async Task CountLogsAsync(string channelName) /// public async Task ClearPendingLogStateAsync(string channelName) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + using (await _mutex.GetLockAsync().ConfigureAwait(false)) { _pendingDbIdentifierGroups.Clear(); _pendingDbIdentifiers.Clear(); @@ -178,7 +179,7 @@ public async Task ClearPendingLogStateAsync(string channelName) /// public async Task GetLogsAsync(string channelName, int limit, List logs) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + using (await _mutex.GetLockAsync().ConfigureAwait(false)) { logs?.Clear(); var retrievedLogs = new List(); @@ -261,7 +262,7 @@ private async Task InitializeDatabaseAsync() /// True if remaining tasks completed in time; false otherwise public Task ShutdownAsync(TimeSpan timeout) { - return _taskLockSource.ShutdownAsync(timeout); + return _mutex.ShutdownAsync(timeout); } private static string GetFullIdentifier(string channelName, string identifier) @@ -280,7 +281,7 @@ private static bool ChannelMatchesIdentifier(string channelName, string identifi /// public void Dispose() { - _taskLockSource.Dispose(); + _mutex.Dispose(); } } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLock.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLock.cs deleted file mode 100644 index c0db956b9..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLock.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; - -namespace Microsoft.Azure.Mobile.Storage -{ - public partial class TaskLock : IDisposable - { - private readonly TaskLockSource _source; - - private TaskLock(TaskLockSource source) - { - _source = source; - } - - public void Dispose() - { - _source.TaskHandlerWasDisposed(); - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs deleted file mode 100644 index 6488a42cf..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.Azure.Mobile.Storage -{ - public partial class TaskLock - { - public class TaskLockSource : IDisposable - { - private readonly object _lockObject = new object(); - private readonly SemaphoreSlim _taskSemaphore = new SemaphoreSlim(1); - private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1, 1); - private bool _isShutdown; - private int _numTasksRemaning; - - public Task ShutdownAsync(TimeSpan timeout) - { - lock (_lockObject) - { - _isShutdown = true; - } - return _taskSemaphore.WaitAsync(timeout); - } - - public TaskLock GetTaskLock() - { - lock (_lockObject) - { - if (_isShutdown) - { - throw new StorageException("Trying to execute task after shutdown requested"); - } - _numTasksRemaning++; - if (_taskSemaphore.CurrentCount == 1) - { - _taskSemaphore.Wait(); - } - } - _mutex.Wait(); - return new TaskLock(this); - } - - - public async Task GetTaskLockAsync() - { - lock (_lockObject) - { - if (_isShutdown) - { - throw new StorageException("Trying to execute task after shutdown requested"); - } - _numTasksRemaning++; - if (_taskSemaphore.CurrentCount == 1) - { - _taskSemaphore.Wait(); - } - } - await _mutex.WaitAsync().ConfigureAwait(false); - return new TaskLock(this); - } - - public void TaskHandlerWasDisposed() - { - _mutex.Release(); - lock (_lockObject) - { - _numTasksRemaning--; - if (_numTasksRemaning == 0 && _isShutdown && _taskSemaphore.CurrentCount == 0) - { - _taskSemaphore.Release(); - } - - } - } - - public void Dispose() - { - _taskSemaphore.Dispose(); - _mutex.Dispose(); - } - } - } -} \ No newline at end of file diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StateKeeper.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StateKeeper.cs deleted file mode 100644 index 47053002c..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StateKeeper.cs +++ /dev/null @@ -1,38 +0,0 @@ -namespace Microsoft.Azure.Mobile.Utils.Synchronization -{ - /// - /// Responsible for keeping track of a current - /// - /// - public class StateKeeper - { - private State _currentState = new State(); - - /// - /// Advances the current state - /// - public void InvalidateState() - { - _currentState = _currentState.GetNextState(); - } - - /// - /// Gets the current state - /// - /// The current state - public State GetStateSnapshot() - { - return _currentState; - } - - /// - /// Checks if the given state is current - /// - /// The state to test - /// True if the current state is current, false otherwise - public bool IsCurrent(State state) - { - return _currentState.Equals(state); - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs index d5caa6e91..7f740566b 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs @@ -11,16 +11,44 @@ namespace Microsoft.Azure.Mobile.Utils.Synchronization /// public class StatefulMutex : IDisposable { + private const string ShutdownExceptionMessage = "Trying to execute task after shutdown requested"; + private const string StateExceptionMessage = "Cannot lock mutex with expired state"; + private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1, 1); - private readonly StateKeeper _stateKeeper; + private State _state = new State(); + private volatile bool _isShutdown; + + /// + /// Gets the current state + /// + /// The current state + public State State + { + get { return _state; } + } + + /// + /// Advances the current state + /// + public void InvalidateState() + { + _state = _state.GetNextState(); + } /// - /// Creates a with an existing + /// Checks if the given state is current /// - /// Tracks the current state for the mutex - public StatefulMutex(StateKeeper stateKeeper) + /// The state to test + /// True if the current state is current, false otherwise + public bool IsCurrent(State state) + { + return _state.Equals(state); + } + + public Task ShutdownAsync(TimeSpan timeout) { - _stateKeeper = stateKeeper; + _isShutdown = true; + return _mutex.WaitAsync(timeout); } /// @@ -29,6 +57,10 @@ public StatefulMutex(StateKeeper stateKeeper) /// public void Lock() { + if (_isShutdown) + { + throw new StatefulMutexException(ShutdownExceptionMessage); + } _mutex.Wait(); } @@ -40,11 +72,28 @@ public void Lock() /// public void Lock(State stateSnapshot) { + if (_isShutdown) + { + throw new StatefulMutexException(ShutdownExceptionMessage); + } _mutex.Wait(); - if (!_stateKeeper.IsCurrent(stateSnapshot)) + if (!IsCurrent(stateSnapshot)) + { + throw new StatefulMutexException(StateExceptionMessage); + } + } + + /// + /// Asynchronously locks the mutex and does not verify any state + /// + /// + public Task LockAsync() + { + if (_isShutdown) { - throw new StatefulMutexException("Cannot lock mutex with expired state"); + throw new StatefulMutexException(ShutdownExceptionMessage); } + return _mutex.WaitAsync(); } /// @@ -55,32 +104,46 @@ public void Lock(State stateSnapshot) /// public async Task LockAsync(State stateSnapshot) { + if (_isShutdown) + { + throw new StatefulMutexException(ShutdownExceptionMessage); + } await _mutex.WaitAsync().ConfigureAwait(false); - if (!_stateKeeper.IsCurrent(stateSnapshot)) + if (!IsCurrent(stateSnapshot)) { Unlock(); - throw new StatefulMutexException("Cannot lock mutex with expired state"); + throw new StatefulMutexException(StateExceptionMessage); } } - /// - /// Asynchronously locks the mutex and does not verify any state - /// - /// - public Task LockAsync() - { - return _mutex.WaitAsync(); - } - /// /// Unlocks the mutex. Consecutive calls will not throw an exception /// public void Unlock() { - if (_mutex.CurrentCount == 0) + if (_mutex.CurrentCount != 0) { - _mutex.Release(); + throw new StatefulMutexException("Trying to unlock not locked mutex"); } + _mutex.Release(); + } + + public LockHolder GetLock() + { + Lock(); + return new LockHolder(this); + } + + public async Task GetLockAsync() + { + await LockAsync().ConfigureAwait(false); + return new LockHolder(this); + } + + public async Task GetLockAsync(State state) + { + await LockAsync(state).ConfigureAwait(false); + return new LockHolder(this); } /// @@ -91,5 +154,19 @@ public void Dispose() _mutex.Dispose(); } + public class LockHolder : IDisposable + { + private StatefulMutex _parent; + + internal LockHolder(StatefulMutex parent) + { + _parent = parent; + } + + public void Dispose() + { + _parent.Unlock(); + } + } } } diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs index e88ca8216..d2f984ce5 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs @@ -35,18 +35,13 @@ public static void CheckLaunchedFromNotification(LaunchActivatedEventArgs e) private void InstanceCheckLaunchedFromNotification(LaunchActivatedEventArgs e) { IDictionary customData = null; - _mutex.Lock(); - try + using (_mutex.GetLock()) { if (!IsInactive) { customData = ParseLaunchString(e?.Arguments); } } - finally - { - _mutex.Unlock(); - } if (customData != null) { PushNotificationReceived?.Invoke(null, new PushNotificationReceivedEventArgs() @@ -68,41 +63,39 @@ private void ApplyEnabledState(bool enabled) if (enabled) { // We expect caller of this method to lock on _mutex, we can't do it here as that lock is not recursive - var stateSnapshot = _stateKeeper.GetStateSnapshot(); + var state = _mutex.State; Task.Run(async () => { var channel = await new WindowsPushNotificationChannelManager().CreatePushNotificationChannelForApplicationAsync() .AsTask().ConfigureAwait(false); try { - _mutex.Lock(stateSnapshot); - var pushToken = channel.Uri; - if (!string.IsNullOrEmpty(pushToken)) + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) { - // Save channel member - _channel = channel; + var pushToken = channel.Uri; + if (!string.IsNullOrEmpty(pushToken)) + { + // Save channel member + _channel = channel; - // Subscribe to push - channel.PushNotificationReceived += OnPushNotificationReceivedHandler; + // Subscribe to push + channel.PushNotificationReceived += OnPushNotificationReceivedHandler; - // Send channel URI to backend - MobileCenterLog.Debug(LogTag, $"Push token '{pushToken}'"); - var pushInstallationLog = new PushInstallationLog(0, null, pushToken, Guid.NewGuid()); - await Channel.EnqueueAsync(pushInstallationLog).ConfigureAwait(false); - } - else - { - MobileCenterLog.Error(LogTag, "Push service registering with Mobile Center backend has failed."); + // Send channel URI to backend + MobileCenterLog.Debug(LogTag, $"Push token '{pushToken}'"); + var pushInstallationLog = new PushInstallationLog(0, null, pushToken, Guid.NewGuid()); + await Channel.EnqueueAsync(pushInstallationLog).ConfigureAwait(false); + } + else + { + MobileCenterLog.Error(LogTag, "Push service registering with Mobile Center backend has failed."); + } } } catch (StatefulMutexException) { MobileCenterLog.Warn(LogTag, "Push Enabled state changed after creating channel."); } - finally - { - _mutex.Unlock(); - } }); } else if (_channel != null) diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs index 67a32376e..34a8090c6 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs @@ -55,15 +55,14 @@ private static bool PlatformEnabled #region instance - private readonly StatefulMutex _mutex; - private readonly StateKeeper _stateKeeper = new StateKeeper(); + private readonly StatefulMutex _mutex = new StatefulMutex(); public override string ServiceName => "Push"; protected override string ChannelName => "push"; + public Push() { - _mutex = new StatefulMutex(_stateKeeper); LogSerializer.AddLogType(PushInstallationLog.JsonIdentifier, typeof(PushInstallationLog)); } @@ -74,16 +73,11 @@ public Push() /// public override void OnChannelGroupReady(IChannelGroup channelGroup, string appSecret) { - _mutex.Lock(); - try + using (_mutex.GetLock()) { base.OnChannelGroupReady(channelGroup, appSecret); ApplyEnabledState(Enabled); } - finally - { - _mutex.Unlock(); - } } public override bool InstanceEnabled @@ -95,21 +89,16 @@ public override bool InstanceEnabled set { - _mutex.Lock(); - try + using (_mutex.GetLock()) { var prevValue = InstanceEnabled; base.InstanceEnabled = value; - _stateKeeper.InvalidateState(); + _mutex.InvalidateState(); if (value != prevValue) { ApplyEnabledState(value); } } - finally - { - _mutex.Unlock(); - } } } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs index 9d83f6354..e8589bf09 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs @@ -22,7 +22,9 @@ public class ChannelTest private readonly TimeSpan _batchTimeSpan = TimeSpan.FromSeconds(1); private const int MaxParallelBatches = 3; private readonly string _appSecret = Guid.NewGuid().ToString(); - private const int DefaultWaitTime = 5000; + + // We wait tasks now and don't need wait more + private const int DefaultWaitTime = 500; // Event semaphores for invokation verification private const int SendingLogSemaphoreIdx = 0; diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/MockChannelGroupFactory.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/MockChannelGroupFactory.cs index 9ec0a4027..110af04f4 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/MockChannelGroupFactory.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/MockChannelGroupFactory.cs @@ -10,7 +10,7 @@ public MockChannelGroupFactory(Mock channelGroupMock) _channelGroupMock = channelGroupMock; } - private readonly Mock _channelGroupMock; + private readonly Mock _channelGroupMock; public IChannelGroup CreateChannelGroup(string appSecret) { diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs index 2ac110548..0a640cf23 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs @@ -337,6 +337,10 @@ public void ConfigureMobileCenterMultipleTimes() public void LogUrlIsNotSetByDefault() { var channelGroupMock = new Mock(); + var channelUnitMock = new Mock(); + channelGroupMock.Setup( + group => group.AddChannel(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(channelUnitMock.Object); MobileCenter.Instance = new MobileCenter(new ApplicationSettings(), new MockChannelGroupFactory(channelGroupMock)); MobileCenter.Configure("appsecret"); @@ -350,6 +354,10 @@ public void LogUrlIsNotSetByDefault() public void SetLogUrlBeforeConfigure() { var channelGroupMock = new Mock(); + var channelUnitMock = new Mock(); + channelGroupMock.Setup( + group => group.AddChannel(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(channelUnitMock.Object); MobileCenter.Instance = new MobileCenter(new ApplicationSettings(), new MockChannelGroupFactory(channelGroupMock)); var customLogUrl = "www dot log url dot com"; @@ -366,6 +374,10 @@ public void SetLogUrlBeforeConfigure() public void SetLogUrlAfterConfigure() { var channelGroupMock = new Mock(); + var channelUnitMock = new Mock(); + channelGroupMock.Setup( + group => group.AddChannel(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) + .Returns(channelUnitMock.Object); MobileCenter.Instance = new MobileCenter(new ApplicationSettings(), new MockChannelGroupFactory(channelGroupMock)); MobileCenter.Configure("appsecret"); diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs index f214166bb..75f55a6fa 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; using System.Linq.Expressions; +using System.Threading; using System.Threading.Tasks; using Microsoft.Azure.Mobile.Ingestion.Models; using Microsoft.Azure.Mobile.Storage; -using Moq; +using Microsoft.Azure.Mobile.Utils.Synchronization; using Microsoft.VisualStudio.TestTools.UnitTesting; -using System.Threading; +using Moq; namespace Microsoft.Azure.Mobile.Test { @@ -75,7 +76,7 @@ public void ShutdownPreventsNewTasks() var storage = new Mobile.Storage.Storage(mockConnection.Object); var result = storage.ShutdownAsync(TimeSpan.FromSeconds(10)).RunNotAsync(); Assert.IsTrue(result); - Assert.ThrowsException( + Assert.ThrowsException( () => storage.GetLogsAsync(It.IsAny(), It.IsAny(), It.IsAny>()).RunNotAsync()); } From 75eade7245d9e4178d59b97678eff53c97c86cd2 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Mon, 22 May 2017 17:04:39 -0700 Subject: [PATCH 12/90] Replace polymorphic serializer from autorest --- MobileCenter-Windows.sln | 2 +- .../Ingestion/Models/CustomPropertiesLog.cs | 176 ---------- .../Ingestion/Models/Device.cs | 326 ------------------ .../Ingestion/Models/Log.cs | 78 ----- .../Ingestion/Models/LogContainer.cs | 52 --- .../Ingestion/Models/LogJsonConverter.cs | 47 --- .../Ingestion/Models/LogSerializer.cs | 64 ---- .../Ingestion/Models/LogWithProperties.cs | 46 --- .../Ingestion/Models/StartServiceLog.cs | 65 ---- ...soft.Azure.Mobile.Windows.Shared.projitems | 16 +- .../Microsoft.Azure.Mobile.Push.UWP/Push.cs | 2 +- .../Ingestion/Models/PushInstallationLog.cs | 2 +- .../Push.cs | 2 +- ...soft.Azure.Mobile.Push.Test.Windows.csproj | 6 - 14 files changed, 12 insertions(+), 872 deletions(-) delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogJsonConverter.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogSerializer.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogWithProperties.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs diff --git a/MobileCenter-Windows.sln b/MobileCenter-Windows.sln index a4562b258..37df19674 100644 --- a/MobileCenter-Windows.sln +++ b/MobileCenter-Windows.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26430.4 +VisualStudioVersion = 15.0.26430.6 MinimumVisualStudioVersion = 10.0.40219.1 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Apps", "Apps", "{AA6821F3-930A-49E4-BA3F-D68255F39F1E}" EndProject diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs deleted file mode 100644 index 9f81a971d..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - /// - /// The custom properties log model. - /// - [JsonObject(JsonIdentifier)] - public class CustomPropertiesLog : Log - { - internal const string JsonIdentifier = "custom_properties"; - private const string PropertyType = "type"; - private const string PropertyName = "name"; - private const string PropertyValue = "value"; - private const string PropertyTypeClear = "clear"; - private const string PropertyTypeBoolean = "boolean"; - private const string PropertyTypeNumber = "number"; - private const string PropertyTypeDatetime = "date_time"; - private const string PropertyTypeString = "string"; - - /// - /// Initializes a new instance of the Log class. - /// - public CustomPropertiesLog() - { - Properties = new Dictionary(); - } - - /// - /// Key/value pair properties. - /// - /// JsonConverter attribute not supported here. - [JsonIgnore] - public IDictionary Properties { get; set; } - - [JsonProperty(PropertyName = "properties")] - internal JArray JsonProperties - { - get { return WriteProperties(Properties); } - set { Properties = ReadProperties(value); } - } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public override void Validate() - { - base.Validate(); - - if (Properties == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Properties)); - } - } - - private static JArray WriteProperties(IDictionary value) - { - if (value == null) - { - return null; - } - var properties = new JArray(); - foreach (var property in value) - { - properties.Add(WriteProperty(property.Key, property.Value)); - } - return properties; - } - - private static JObject WriteProperty(string key, object value) - { - var property = new JObject(); - property.Add(PropertyName, key); - if (value == null) - { - property.Add(PropertyType, PropertyTypeClear); - } - else - { - var typeCode = Convert.GetTypeCode(value); - switch (typeCode) - { - case TypeCode.Boolean: - property.Add(PropertyType, PropertyTypeBoolean); - property.Add(PropertyValue, JToken.FromObject(value)); - break; - case TypeCode.Char: - case TypeCode.String: - property.Add(PropertyType, PropertyTypeString); - property.Add(PropertyValue, JToken.FromObject(value)); - break; - case TypeCode.SByte: - case TypeCode.Byte: - case TypeCode.Int16: - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - property.Add(PropertyType, PropertyTypeNumber); - property.Add(PropertyValue, JToken.FromObject(value)); - break; - case TypeCode.DateTime: - property.Add(PropertyType, PropertyTypeDatetime); - property.Add(PropertyValue, JToken.FromObject(value)); - break; - default: - throw new JsonException("Invalid value type"); - } - } - return property; - } - - private static IDictionary ReadProperties(JArray value) - { - if (value == null) - { - return null; - } - var properties = new Dictionary(); - foreach (var property in value.Children()) - { - var pair = ReadProperty((JObject)property); - properties.Add(pair.Key, pair.Value); - } - return properties; - } - - private static KeyValuePair ReadProperty(JObject property) - { - string type = property.Value(PropertyType); - string name = property.Value(PropertyName); - object value; - switch (type) - { - case PropertyTypeClear: - value = null; - break; - case PropertyTypeBoolean: - value = property.Value(PropertyValue); - break; - case PropertyTypeNumber: - switch (property.GetValue(PropertyValue).Type) - { - case JTokenType.Integer: - value = property.Value(PropertyValue); - break; - case JTokenType.Float: - value = property.Value(PropertyValue); - break; - default: - throw new JsonException("Invalid value type"); - } - break; - case PropertyTypeDatetime: - value = property.Value(PropertyValue); - break; - case PropertyTypeString: - value = property.Value(PropertyValue); - break; - default: - throw new JsonException("Invalid value type"); - } - return new KeyValuePair(name, value); - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs deleted file mode 100644 index 6183efb01..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using Newtonsoft.Json; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - /// - /// Device characteristics. - /// - public class Device - { - /// - /// Initializes a new instance of the Device class. - /// - public Device() { } - - /// - /// Initializes a new instance of the Device class. - /// - /// Name of the SDK. Consists of the name of the - /// SDK and the platform, e.g. "mobilecenter.ios", "hockeysdk.android". - /// - /// Version of the SDK in semver format, e.g. - /// "1.2.0" or "0.12.3-alpha.1". - /// - /// Device model (example: iPad2,3). - /// - /// Device manufacturer (example: HTC). - /// - /// OS name (example: iOS). The following OS names - /// are standardized (non-exclusive): Android, iOS, macOS, tvOS, - /// Windows. - /// - /// OS version (example: 9.3.0). - /// - /// Language code (example: en_US). - /// - /// The offset in minutes from UTC for the - /// device time zone, including daylight savings time. - /// - /// Screen size of the device in pixels - /// (example: 640x480). - /// - /// Application version name, e.g. 1.1.0 - /// - /// The app's build number, e.g. 42. - /// - /// Version of the wrapper SDK in - /// semver format. When the SDK is embedding another base SDK (for - /// example Xamarin.Android wraps Android), the Xamarin specific - /// version is populated into this field while sdkVersion refers to the - /// original Android SDK. - /// - /// Name of the wrapper SDK. Consists of - /// the name of the SDK and the wrapper platform, e.g. - /// "mobilecenter.xamarin", "hockeysdk.cordova". - /// - /// OS build code (example: LMY47X). - /// - /// API level when applicable like in Android - /// (example: 15). - /// - /// Carrier name (for mobile devices). - /// - /// Carrier country code (for mobile - /// devices). - /// - /// The bundle identifier, package - /// identifier, or namespace, depending on what the individual - /// plattforms use, .e.g com.microsoft.example. - /// - /// Label that is used to identify - /// application code 'version' released via Live Update beacon running - /// on device - /// - /// Identifier of environment - /// that current application release belongs to, deployment key then - /// maps to environment like Production, Staging. - /// - /// Hash of all files (ReactNative - /// or Cordova) deployed to device via LiveUpdate beacon. Helps - /// identify the Release version on device or need to download updates - /// in future - /// - public Device(string sdkName, string sdkVersion, string model, string oemName, string osName, string osVersion, string locale, int timeZoneOffset, string screenSize, string appVersion, string appBuild, string wrapperSdkVersion = default(string), string wrapperSdkName = default(string), string osBuild = default(string), int? osApiLevel = default(int?), string carrierName = default(string), string carrierCountry = default(string), string appNamespace = default(string), string liveUpdateReleaseLabel = default(string), string liveUpdateDeploymentKey = default(string), string liveUpdatePackageHash = default(string)) - { - SdkName = sdkName; - SdkVersion = sdkVersion; - WrapperSdkVersion = wrapperSdkVersion; - WrapperSdkName = wrapperSdkName; - Model = model; - OemName = oemName; - OsName = osName; - OsVersion = osVersion; - OsBuild = osBuild; - OsApiLevel = osApiLevel; - Locale = locale; - TimeZoneOffset = timeZoneOffset; - ScreenSize = screenSize; - AppVersion = appVersion; - CarrierName = carrierName; - CarrierCountry = carrierCountry; - AppBuild = appBuild; - AppNamespace = appNamespace; - LiveUpdateReleaseLabel = liveUpdateReleaseLabel; - LiveUpdateDeploymentKey = liveUpdateDeploymentKey; - LiveUpdatePackageHash = liveUpdatePackageHash; - } - - /// - /// Gets or sets name of the SDK. Consists of the name of the SDK and - /// the platform, e.g. "mobilecenter.ios", "hockeysdk.android". - /// - /// - [JsonProperty(PropertyName = "sdk_name")] - public string SdkName { get; set; } - - /// - /// Gets or sets version of the SDK in semver format, e.g. "1.2.0" or - /// "0.12.3-alpha.1". - /// - /// - [JsonProperty(PropertyName = "sdk_version")] - public string SdkVersion { get; set; } - - /// - /// Gets or sets version of the wrapper SDK in semver format. When the - /// SDK is embedding another base SDK (for example Xamarin.Android - /// wraps Android), the Xamarin specific version is populated into this - /// field while sdkVersion refers to the original Android SDK. - /// - /// - [JsonProperty(PropertyName = "wrapper_sdk_version")] - public string WrapperSdkVersion { get; set; } - - /// - /// Gets or sets name of the wrapper SDK. Consists of the name of the - /// SDK and the wrapper platform, e.g. "mobilecenter.xamarin", - /// "hockeysdk.cordova". - /// - /// - [JsonProperty(PropertyName = "wrapper_sdk_name")] - public string WrapperSdkName { get; set; } - - /// - /// Gets or sets device model (example: iPad2,3). - /// - /// - [JsonProperty(PropertyName = "model")] - public string Model { get; set; } - - /// - /// Gets or sets device manufacturer (example: HTC). - /// - /// - [JsonProperty(PropertyName = "oem_name")] - public string OemName { get; set; } - - /// - /// Gets or sets OS name (example: iOS). The following OS names are - /// standardized (non-exclusive): Android, iOS, macOS, tvOS, Windows. - /// - /// - [JsonProperty(PropertyName = "os_name")] - public string OsName { get; set; } - - /// - /// Gets or sets OS version (example: 9.3.0). - /// - /// - [JsonProperty(PropertyName = "os_version")] - public string OsVersion { get; set; } - - /// - /// Gets or sets OS build code (example: LMY47X). - /// - /// - [JsonProperty(PropertyName = "os_build")] - public string OsBuild { get; set; } - - /// - /// Gets or sets API level when applicable like in Android (example: - /// 15). - /// - /// - [JsonProperty(PropertyName = "os_api_level")] - public int? OsApiLevel { get; set; } - - /// - /// Gets or sets language code (example: en_US). - /// - /// - [JsonProperty(PropertyName = "locale")] - public string Locale { get; set; } - - /// - /// Gets or sets the offset in minutes from UTC for the device time - /// zone, including daylight savings time. - /// - /// - [JsonProperty(PropertyName = "time_zone_offset")] - public int TimeZoneOffset { get; set; } - - /// - /// Gets or sets screen size of the device in pixels (example: - /// 640x480). - /// - /// - [JsonProperty(PropertyName = "screen_size")] - public string ScreenSize { get; set; } - - /// - /// Gets or sets application version name, e.g. 1.1.0 - /// - /// - [JsonProperty(PropertyName = "app_version")] - public string AppVersion { get; set; } - - /// - /// Gets or sets carrier name (for mobile devices). - /// - /// - [JsonProperty(PropertyName = "carrier_name")] - public string CarrierName { get; set; } - - /// - /// Gets or sets carrier country code (for mobile devices). - /// - /// - [JsonProperty(PropertyName = "carrier_country")] - public string CarrierCountry { get; set; } - - /// - /// Gets or sets the app's build number, e.g. 42. - /// - /// - [JsonProperty(PropertyName = "app_build")] - public string AppBuild { get; set; } - - /// - /// Gets or sets the bundle identifier, package identifier, or - /// namespace, depending on what the individual plattforms use, .e.g - /// com.microsoft.example. - /// - /// - [JsonProperty(PropertyName = "app_namespace")] - public string AppNamespace { get; set; } - - /// - /// Gets or sets label that is used to identify application code - /// 'version' released via Live Update beacon running on device - /// - /// - [JsonProperty(PropertyName = "live_update_release_label")] - public string LiveUpdateReleaseLabel { get; set; } - - /// - /// Gets or sets identifier of environment that current application - /// release belongs to, deployment key then maps to environment like - /// Production, Staging. - /// - /// - [JsonProperty(PropertyName = "live_update_deployment_key")] - public string LiveUpdateDeploymentKey { get; set; } - - /// - /// Gets or sets hash of all files (ReactNative or Cordova) deployed to - /// device via LiveUpdate beacon. Helps identify the Release version on - /// device or need to download updates in future - /// - /// - [JsonProperty(PropertyName = "live_update_package_hash")] - public string LiveUpdatePackageHash { get; set; } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public virtual void Validate() - { - if (SdkName == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkName"); - } - if (SdkVersion == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkVersion"); - } - if (Model == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Model"); - } - if (OemName == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OemName"); - } - if (OsName == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsName"); - } - if (OsVersion == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsVersion"); - } - if (Locale == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Locale"); - } - if (ScreenSize == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "ScreenSize"); - } - if (AppVersion == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppVersion"); - } - if (AppBuild == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppBuild"); - } - } - } -} - diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs deleted file mode 100644 index b3c160032..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using Newtonsoft.Json; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public abstract class Log - { - /// - /// Initializes a new instance of the Log class. - /// - protected Log() { } - - /// - /// Initializes a new instance of the Log class. - /// - /// Corresponds to the number of milliseconds - /// elapsed between the time the request is sent and the time the log - /// is emitted. - /// When tracking an analytics session, logs can be - /// part of the session by specifying this identifier. - /// This attribute is optional, a missing value means the session - /// tracking is disabled (like when using only error reporting - /// feature). - /// Concrete types like StartSessionLog or PageLog are always part of a - /// session and always include this identifier. - /// - /// Description of the device emitting the log - protected Log(long toffset, Device device, System.Guid? sid = default(System.Guid?)) - { - Toffset = toffset; - Sid = sid; - Device = device; - } - - /// - /// Gets or sets corresponds to the number of milliseconds elapsed - /// between the time the request is sent and the time the log is - /// emitted. - /// - [JsonProperty(PropertyName = "toffset")] - public long Toffset { get; set; } - - /// - /// Gets or sets when tracking an analytics session, logs can be part - /// of the session by specifying this identifier. - /// This attribute is optional, a missing value means the session - /// tracking is disabled (like when using only error reporting - /// feature). - /// Concrete types like StartSessionLog or PageLog are always part of a - /// session and always include this identifier. - /// - /// - [JsonProperty(PropertyName = "sid")] - public System.Guid? Sid { get; set; } - - /// - /// - [JsonProperty(PropertyName = "device")] - public Device Device { get; set; } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public virtual void Validate() - { - if (Device == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Device"); - } - Device.Validate(); - } - } -} - diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs deleted file mode 100644 index dd81f648d..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using Newtonsoft.Json; -using System.Collections.Generic; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public class LogContainer - { - /// - /// Initializes a new instance of the LogContainer class. - /// - public LogContainer() { } - - /// - /// Initializes a new instance of the LogContainer class. - /// - /// The list of logs - public LogContainer(IList logs) - { - Logs = logs; - } - - /// - /// Gets or sets the list of logs - /// - [JsonProperty(PropertyName = "logs")] - public IList Logs { get; set; } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public virtual void Validate() - { - if (Logs == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Logs"); - } - if (Logs.Count < 1) - { - throw new Rest.ValidationException(Rest.ValidationRules.MinItems, "Logs", 1); - } - foreach (var element in Logs) - { - element?.Validate(); - } - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogJsonConverter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogJsonConverter.cs deleted file mode 100644 index 0487fd80b..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogJsonConverter.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using Microsoft.Rest.Serialization; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public class LogJsonConverter : JsonConverter - { - private readonly Dictionary _logTypes = new Dictionary(); - private readonly PolymorphicDeserializeJsonConverter _converter = new PolymorphicDeserializeJsonConverter(LogSerializer.TypeIdKey); - private readonly object _jsonConverterLock = new object(); - - public void AddLogType(string typeName, Type type) - { - lock (_jsonConverterLock) - { - _logTypes[typeName] = type; - } - } - - public override bool CanConvert(Type objectType) - { - return _converter.CanConvert(objectType); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - lock (_jsonConverterLock) - { - var jsonObject = JObject.Load(reader); - var typeName = jsonObject.GetValue(LogSerializer.TypeIdKey)?.ToString(); - if (typeName == null || !_logTypes.ContainsKey(typeName)) - { - throw new JsonReaderException("Could not identify type of log"); - } - return _converter.ReadJson(jsonObject.CreateReader(), _logTypes[typeName], existingValue, serializer); - } - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - /* No-op */ - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogSerializer.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogSerializer.cs deleted file mode 100644 index 09faf1b45..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogSerializer.cs +++ /dev/null @@ -1,64 +0,0 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public static class LogSerializer - { - private static readonly LogJsonConverter Converter = new LogJsonConverter(); - private static readonly JsonSerializerSettings SerializationSettings; - private static readonly JsonSerializerSettings DeserializationSettings; - internal const string TypeIdKey = "type"; - - static LogSerializer() - { - SerializationSettings = new JsonSerializerSettings - { - Formatting = Formatting.Indented, - DateFormatHandling = DateFormatHandling.IsoDateFormat, - DateTimeZoneHandling = DateTimeZoneHandling.Utc, - NullValueHandling = NullValueHandling.Ignore, - ReferenceLoopHandling = ReferenceLoopHandling.Serialize, - ContractResolver = new Rest.Serialization.ReadOnlyJsonContractResolver(), - Converters = new List - { - new Rest.Serialization.Iso8601TimeSpanConverter(), - new Rest.Serialization.PolymorphicSerializeJsonConverter(TypeIdKey) - - } - }; - DeserializationSettings = new JsonSerializerSettings - { - DateFormatHandling = DateFormatHandling.IsoDateFormat, - DateTimeZoneHandling = DateTimeZoneHandling.Utc, - NullValueHandling = NullValueHandling.Ignore, - ReferenceLoopHandling = ReferenceLoopHandling.Serialize, - ContractResolver = new Rest.Serialization.ReadOnlyJsonContractResolver(), - Converters = new List - { - new Rest.Serialization.Iso8601TimeSpanConverter(), - Converter - } - }; - } - - public static void AddLogType(string typeName, Type logType) - { - Converter.AddLogType(typeName, logType); - } - public static string Serialize(LogContainer logContainer) - { - return Rest.Serialization.SafeJsonConvert.SerializeObject(logContainer, SerializationSettings); - } - public static string Serialize(Log log) - { - return Rest.Serialization.SafeJsonConvert.SerializeObject(log, SerializationSettings); - } - - public static Log DeserializeLog(string json) - { - return Rest.Serialization.SafeJsonConvert.DeserializeObject(json, DeserializationSettings); - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogWithProperties.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogWithProperties.cs deleted file mode 100644 index 9706000ce..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogWithProperties.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using Newtonsoft.Json; -using System.Collections.Generic; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public abstract class LogWithProperties : Log - { - /// - /// Initializes a new instance of the LogWithProperties class. - /// - protected LogWithProperties() { } - - /// - /// Initializes a new instance of the LogWithProperties class. - /// - /// Corresponds to the number of milliseconds - /// elapsed between the time the request is sent and the time the log - /// is emitted. - /// When tracking an analytics session, logs can be - /// part of the session by specifying this identifier. - /// This attribute is optional, a missing value means the session - /// tracking is disabled (like when using only error reporting - /// feature). - /// Concrete types like StartSessionLog or PageLog are always part of a - /// session and always include this identifier. - /// - /// Additional key/value pair parameters. - /// - ///Description of the device emitting the log - protected LogWithProperties(long toffset, Device device, System.Guid? sid = default(System.Guid?), IDictionary properties = default(IDictionary)) - : base(toffset, device, sid) - { - Properties = properties; - } - - /// - /// Gets or sets additional key/value pair parameters. - /// - /// - [JsonProperty(PropertyName = "properties")] - public IDictionary Properties { get; set; } - } -} - diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs deleted file mode 100644 index e1428e75f..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - /// - /// Log type for sending information about which services have been started - /// - [JsonObject(JsonIdentifier)] - public class StartServiceLog : Log - { - internal const string JsonIdentifier = "start_service"; - - /// - /// Initializes a new instance of the Log class. - /// - public StartServiceLog() - { - Services = new List(); - } - - /// - /// Initializes a new instance of the Log class - /// - /// >Corresponds to the number of milliseconds - /// elapsed between the time the request is sent and the time the log - /// is emitted. - /// Device and SDK information - /// Names of services which started with SDK - /// When tracking an analytics session, logs can be - /// part of the session by specifying this identifier. - /// This attribute is optional, a missing value means the session - /// tracking is disabled (like when using only error reporting - /// feature). - /// Concrete types like StartSessionLog or PageLog are always part of a - /// session and always include this identifier. - public StartServiceLog(long toffset, Device device, IEnumerable services, System.Guid? sid = default(System.Guid?)) - : base(toffset, device, sid) - { - Services = new List(services); - } - - /// - /// Services names which have been started - /// - [JsonProperty(PropertyName = "services")] - public List Services { get; set; } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public override void Validate() - { - base.Validate(); - - if (Services == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Services)); - } - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems index 527453615..0cb9ae922 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems @@ -21,7 +21,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -43,12 +43,12 @@ - - - - - - + + + + + + diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs index 309004568..c9eeae9c3 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Push.cs @@ -1,4 +1,4 @@ -using Microsoft.Azure.Mobile.Push.Shared.Ingestion.Models; +using Microsoft.Azure.Mobile.Push.Ingestion.Models; using Microsoft.Azure.Mobile.Utils; using Microsoft.Azure.Mobile.Utils.Synchronization; using Newtonsoft.Json; diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Ingestion/Models/PushInstallationLog.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Ingestion/Models/PushInstallationLog.cs index fc247b493..cd7b9ddc3 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Ingestion/Models/PushInstallationLog.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Ingestion/Models/PushInstallationLog.cs @@ -1,7 +1,7 @@ using Microsoft.Azure.Mobile.Ingestion.Models; using Newtonsoft.Json; -namespace Microsoft.Azure.Mobile.Push.Shared.Ingestion.Models +namespace Microsoft.Azure.Mobile.Push.Ingestion.Models { [JsonObject(JsonIdentifier)] public class PushInstallationLog : Log diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs index 67a32376e..b3dbe420a 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs @@ -1,6 +1,6 @@ using Microsoft.Azure.Mobile.Channel; using Microsoft.Azure.Mobile.Ingestion.Models; -using Microsoft.Azure.Mobile.Push.Shared.Ingestion.Models; +using Microsoft.Azure.Mobile.Push.Ingestion.Models; using Microsoft.Azure.Mobile.Utils.Synchronization; namespace Microsoft.Azure.Mobile.Push diff --git a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj index 932d6b266..b74072fd7 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj +++ b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj @@ -65,12 +65,6 @@ - - ..\..\..\..\..\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.FoundationContract\2.0.0.0\Windows.Foundation.FoundationContract.winmd - - - ..\..\..\..\..\Program Files (x86)\Windows Kits\10\References\Windows.Foundation.UniversalApiContract\3.0.0.0\Windows.Foundation.UniversalApiContract.winmd - From 54276d091ebe98ae193c471c22986b0e38db0332 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Mon, 22 May 2017 17:05:00 -0700 Subject: [PATCH 13/90] Re-add Ingetion models --- .../Http/Models/CustomPropertiesLog.cs | 176 ++++++++++ .../Ingestion/Http/Models/Device.cs | 326 ++++++++++++++++++ .../Ingestion/Http/Models/Log.cs | 78 +++++ .../Ingestion/Http/Models/LogContainer.cs | 52 +++ .../Ingestion/Http/Models/LogJsonConverter.cs | 67 ++++ .../Ingestion/Http/Models/LogSerializer.cs | 47 +++ .../Http/Models/LogWithProperties.cs | 46 +++ .../Ingestion/Http/Models/StartServiceLog.cs | 65 ++++ 8 files changed, 857 insertions(+) create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/CustomPropertiesLog.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Device.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Log.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogContainer.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogJsonConverter.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogSerializer.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogWithProperties.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/StartServiceLog.cs diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/CustomPropertiesLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/CustomPropertiesLog.cs new file mode 100644 index 000000000..9f81a971d --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/CustomPropertiesLog.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + /// + /// The custom properties log model. + /// + [JsonObject(JsonIdentifier)] + public class CustomPropertiesLog : Log + { + internal const string JsonIdentifier = "custom_properties"; + private const string PropertyType = "type"; + private const string PropertyName = "name"; + private const string PropertyValue = "value"; + private const string PropertyTypeClear = "clear"; + private const string PropertyTypeBoolean = "boolean"; + private const string PropertyTypeNumber = "number"; + private const string PropertyTypeDatetime = "date_time"; + private const string PropertyTypeString = "string"; + + /// + /// Initializes a new instance of the Log class. + /// + public CustomPropertiesLog() + { + Properties = new Dictionary(); + } + + /// + /// Key/value pair properties. + /// + /// JsonConverter attribute not supported here. + [JsonIgnore] + public IDictionary Properties { get; set; } + + [JsonProperty(PropertyName = "properties")] + internal JArray JsonProperties + { + get { return WriteProperties(Properties); } + set { Properties = ReadProperties(value); } + } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public override void Validate() + { + base.Validate(); + + if (Properties == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Properties)); + } + } + + private static JArray WriteProperties(IDictionary value) + { + if (value == null) + { + return null; + } + var properties = new JArray(); + foreach (var property in value) + { + properties.Add(WriteProperty(property.Key, property.Value)); + } + return properties; + } + + private static JObject WriteProperty(string key, object value) + { + var property = new JObject(); + property.Add(PropertyName, key); + if (value == null) + { + property.Add(PropertyType, PropertyTypeClear); + } + else + { + var typeCode = Convert.GetTypeCode(value); + switch (typeCode) + { + case TypeCode.Boolean: + property.Add(PropertyType, PropertyTypeBoolean); + property.Add(PropertyValue, JToken.FromObject(value)); + break; + case TypeCode.Char: + case TypeCode.String: + property.Add(PropertyType, PropertyTypeString); + property.Add(PropertyValue, JToken.FromObject(value)); + break; + case TypeCode.SByte: + case TypeCode.Byte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Int32: + case TypeCode.UInt32: + case TypeCode.Int64: + case TypeCode.UInt64: + case TypeCode.Single: + case TypeCode.Double: + case TypeCode.Decimal: + property.Add(PropertyType, PropertyTypeNumber); + property.Add(PropertyValue, JToken.FromObject(value)); + break; + case TypeCode.DateTime: + property.Add(PropertyType, PropertyTypeDatetime); + property.Add(PropertyValue, JToken.FromObject(value)); + break; + default: + throw new JsonException("Invalid value type"); + } + } + return property; + } + + private static IDictionary ReadProperties(JArray value) + { + if (value == null) + { + return null; + } + var properties = new Dictionary(); + foreach (var property in value.Children()) + { + var pair = ReadProperty((JObject)property); + properties.Add(pair.Key, pair.Value); + } + return properties; + } + + private static KeyValuePair ReadProperty(JObject property) + { + string type = property.Value(PropertyType); + string name = property.Value(PropertyName); + object value; + switch (type) + { + case PropertyTypeClear: + value = null; + break; + case PropertyTypeBoolean: + value = property.Value(PropertyValue); + break; + case PropertyTypeNumber: + switch (property.GetValue(PropertyValue).Type) + { + case JTokenType.Integer: + value = property.Value(PropertyValue); + break; + case JTokenType.Float: + value = property.Value(PropertyValue); + break; + default: + throw new JsonException("Invalid value type"); + } + break; + case PropertyTypeDatetime: + value = property.Value(PropertyValue); + break; + case PropertyTypeString: + value = property.Value(PropertyValue); + break; + default: + throw new JsonException("Invalid value type"); + } + return new KeyValuePair(name, value); + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Device.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Device.cs new file mode 100644 index 000000000..6183efb01 --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Device.cs @@ -0,0 +1,326 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +using Newtonsoft.Json; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + /// + /// Device characteristics. + /// + public class Device + { + /// + /// Initializes a new instance of the Device class. + /// + public Device() { } + + /// + /// Initializes a new instance of the Device class. + /// + /// Name of the SDK. Consists of the name of the + /// SDK and the platform, e.g. "mobilecenter.ios", "hockeysdk.android". + /// + /// Version of the SDK in semver format, e.g. + /// "1.2.0" or "0.12.3-alpha.1". + /// + /// Device model (example: iPad2,3). + /// + /// Device manufacturer (example: HTC). + /// + /// OS name (example: iOS). The following OS names + /// are standardized (non-exclusive): Android, iOS, macOS, tvOS, + /// Windows. + /// + /// OS version (example: 9.3.0). + /// + /// Language code (example: en_US). + /// + /// The offset in minutes from UTC for the + /// device time zone, including daylight savings time. + /// + /// Screen size of the device in pixels + /// (example: 640x480). + /// + /// Application version name, e.g. 1.1.0 + /// + /// The app's build number, e.g. 42. + /// + /// Version of the wrapper SDK in + /// semver format. When the SDK is embedding another base SDK (for + /// example Xamarin.Android wraps Android), the Xamarin specific + /// version is populated into this field while sdkVersion refers to the + /// original Android SDK. + /// + /// Name of the wrapper SDK. Consists of + /// the name of the SDK and the wrapper platform, e.g. + /// "mobilecenter.xamarin", "hockeysdk.cordova". + /// + /// OS build code (example: LMY47X). + /// + /// API level when applicable like in Android + /// (example: 15). + /// + /// Carrier name (for mobile devices). + /// + /// Carrier country code (for mobile + /// devices). + /// + /// The bundle identifier, package + /// identifier, or namespace, depending on what the individual + /// plattforms use, .e.g com.microsoft.example. + /// + /// Label that is used to identify + /// application code 'version' released via Live Update beacon running + /// on device + /// + /// Identifier of environment + /// that current application release belongs to, deployment key then + /// maps to environment like Production, Staging. + /// + /// Hash of all files (ReactNative + /// or Cordova) deployed to device via LiveUpdate beacon. Helps + /// identify the Release version on device or need to download updates + /// in future + /// + public Device(string sdkName, string sdkVersion, string model, string oemName, string osName, string osVersion, string locale, int timeZoneOffset, string screenSize, string appVersion, string appBuild, string wrapperSdkVersion = default(string), string wrapperSdkName = default(string), string osBuild = default(string), int? osApiLevel = default(int?), string carrierName = default(string), string carrierCountry = default(string), string appNamespace = default(string), string liveUpdateReleaseLabel = default(string), string liveUpdateDeploymentKey = default(string), string liveUpdatePackageHash = default(string)) + { + SdkName = sdkName; + SdkVersion = sdkVersion; + WrapperSdkVersion = wrapperSdkVersion; + WrapperSdkName = wrapperSdkName; + Model = model; + OemName = oemName; + OsName = osName; + OsVersion = osVersion; + OsBuild = osBuild; + OsApiLevel = osApiLevel; + Locale = locale; + TimeZoneOffset = timeZoneOffset; + ScreenSize = screenSize; + AppVersion = appVersion; + CarrierName = carrierName; + CarrierCountry = carrierCountry; + AppBuild = appBuild; + AppNamespace = appNamespace; + LiveUpdateReleaseLabel = liveUpdateReleaseLabel; + LiveUpdateDeploymentKey = liveUpdateDeploymentKey; + LiveUpdatePackageHash = liveUpdatePackageHash; + } + + /// + /// Gets or sets name of the SDK. Consists of the name of the SDK and + /// the platform, e.g. "mobilecenter.ios", "hockeysdk.android". + /// + /// + [JsonProperty(PropertyName = "sdk_name")] + public string SdkName { get; set; } + + /// + /// Gets or sets version of the SDK in semver format, e.g. "1.2.0" or + /// "0.12.3-alpha.1". + /// + /// + [JsonProperty(PropertyName = "sdk_version")] + public string SdkVersion { get; set; } + + /// + /// Gets or sets version of the wrapper SDK in semver format. When the + /// SDK is embedding another base SDK (for example Xamarin.Android + /// wraps Android), the Xamarin specific version is populated into this + /// field while sdkVersion refers to the original Android SDK. + /// + /// + [JsonProperty(PropertyName = "wrapper_sdk_version")] + public string WrapperSdkVersion { get; set; } + + /// + /// Gets or sets name of the wrapper SDK. Consists of the name of the + /// SDK and the wrapper platform, e.g. "mobilecenter.xamarin", + /// "hockeysdk.cordova". + /// + /// + [JsonProperty(PropertyName = "wrapper_sdk_name")] + public string WrapperSdkName { get; set; } + + /// + /// Gets or sets device model (example: iPad2,3). + /// + /// + [JsonProperty(PropertyName = "model")] + public string Model { get; set; } + + /// + /// Gets or sets device manufacturer (example: HTC). + /// + /// + [JsonProperty(PropertyName = "oem_name")] + public string OemName { get; set; } + + /// + /// Gets or sets OS name (example: iOS). The following OS names are + /// standardized (non-exclusive): Android, iOS, macOS, tvOS, Windows. + /// + /// + [JsonProperty(PropertyName = "os_name")] + public string OsName { get; set; } + + /// + /// Gets or sets OS version (example: 9.3.0). + /// + /// + [JsonProperty(PropertyName = "os_version")] + public string OsVersion { get; set; } + + /// + /// Gets or sets OS build code (example: LMY47X). + /// + /// + [JsonProperty(PropertyName = "os_build")] + public string OsBuild { get; set; } + + /// + /// Gets or sets API level when applicable like in Android (example: + /// 15). + /// + /// + [JsonProperty(PropertyName = "os_api_level")] + public int? OsApiLevel { get; set; } + + /// + /// Gets or sets language code (example: en_US). + /// + /// + [JsonProperty(PropertyName = "locale")] + public string Locale { get; set; } + + /// + /// Gets or sets the offset in minutes from UTC for the device time + /// zone, including daylight savings time. + /// + /// + [JsonProperty(PropertyName = "time_zone_offset")] + public int TimeZoneOffset { get; set; } + + /// + /// Gets or sets screen size of the device in pixels (example: + /// 640x480). + /// + /// + [JsonProperty(PropertyName = "screen_size")] + public string ScreenSize { get; set; } + + /// + /// Gets or sets application version name, e.g. 1.1.0 + /// + /// + [JsonProperty(PropertyName = "app_version")] + public string AppVersion { get; set; } + + /// + /// Gets or sets carrier name (for mobile devices). + /// + /// + [JsonProperty(PropertyName = "carrier_name")] + public string CarrierName { get; set; } + + /// + /// Gets or sets carrier country code (for mobile devices). + /// + /// + [JsonProperty(PropertyName = "carrier_country")] + public string CarrierCountry { get; set; } + + /// + /// Gets or sets the app's build number, e.g. 42. + /// + /// + [JsonProperty(PropertyName = "app_build")] + public string AppBuild { get; set; } + + /// + /// Gets or sets the bundle identifier, package identifier, or + /// namespace, depending on what the individual plattforms use, .e.g + /// com.microsoft.example. + /// + /// + [JsonProperty(PropertyName = "app_namespace")] + public string AppNamespace { get; set; } + + /// + /// Gets or sets label that is used to identify application code + /// 'version' released via Live Update beacon running on device + /// + /// + [JsonProperty(PropertyName = "live_update_release_label")] + public string LiveUpdateReleaseLabel { get; set; } + + /// + /// Gets or sets identifier of environment that current application + /// release belongs to, deployment key then maps to environment like + /// Production, Staging. + /// + /// + [JsonProperty(PropertyName = "live_update_deployment_key")] + public string LiveUpdateDeploymentKey { get; set; } + + /// + /// Gets or sets hash of all files (ReactNative or Cordova) deployed to + /// device via LiveUpdate beacon. Helps identify the Release version on + /// device or need to download updates in future + /// + /// + [JsonProperty(PropertyName = "live_update_package_hash")] + public string LiveUpdatePackageHash { get; set; } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public virtual void Validate() + { + if (SdkName == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkName"); + } + if (SdkVersion == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkVersion"); + } + if (Model == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Model"); + } + if (OemName == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OemName"); + } + if (OsName == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsName"); + } + if (OsVersion == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsVersion"); + } + if (Locale == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Locale"); + } + if (ScreenSize == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "ScreenSize"); + } + if (AppVersion == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppVersion"); + } + if (AppBuild == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppBuild"); + } + } + } +} + diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Log.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Log.cs new file mode 100644 index 000000000..b3c160032 --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Log.cs @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +using Newtonsoft.Json; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + public abstract class Log + { + /// + /// Initializes a new instance of the Log class. + /// + protected Log() { } + + /// + /// Initializes a new instance of the Log class. + /// + /// Corresponds to the number of milliseconds + /// elapsed between the time the request is sent and the time the log + /// is emitted. + /// When tracking an analytics session, logs can be + /// part of the session by specifying this identifier. + /// This attribute is optional, a missing value means the session + /// tracking is disabled (like when using only error reporting + /// feature). + /// Concrete types like StartSessionLog or PageLog are always part of a + /// session and always include this identifier. + /// + /// Description of the device emitting the log + protected Log(long toffset, Device device, System.Guid? sid = default(System.Guid?)) + { + Toffset = toffset; + Sid = sid; + Device = device; + } + + /// + /// Gets or sets corresponds to the number of milliseconds elapsed + /// between the time the request is sent and the time the log is + /// emitted. + /// + [JsonProperty(PropertyName = "toffset")] + public long Toffset { get; set; } + + /// + /// Gets or sets when tracking an analytics session, logs can be part + /// of the session by specifying this identifier. + /// This attribute is optional, a missing value means the session + /// tracking is disabled (like when using only error reporting + /// feature). + /// Concrete types like StartSessionLog or PageLog are always part of a + /// session and always include this identifier. + /// + /// + [JsonProperty(PropertyName = "sid")] + public System.Guid? Sid { get; set; } + + /// + /// + [JsonProperty(PropertyName = "device")] + public Device Device { get; set; } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public virtual void Validate() + { + if (Device == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Device"); + } + Device.Validate(); + } + } +} + diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogContainer.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogContainer.cs new file mode 100644 index 000000000..dd81f648d --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogContainer.cs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + public class LogContainer + { + /// + /// Initializes a new instance of the LogContainer class. + /// + public LogContainer() { } + + /// + /// Initializes a new instance of the LogContainer class. + /// + /// The list of logs + public LogContainer(IList logs) + { + Logs = logs; + } + + /// + /// Gets or sets the list of logs + /// + [JsonProperty(PropertyName = "logs")] + public IList Logs { get; set; } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public virtual void Validate() + { + if (Logs == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Logs"); + } + if (Logs.Count < 1) + { + throw new Rest.ValidationException(Rest.ValidationRules.MinItems, "Logs", 1); + } + foreach (var element in Logs) + { + element?.Validate(); + } + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogJsonConverter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogJsonConverter.cs new file mode 100644 index 000000000..457c11cc9 --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogJsonConverter.cs @@ -0,0 +1,67 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + public class LogJsonConverter : JsonConverter + { + private readonly Dictionary _logTypes = new Dictionary(); + private readonly object _jsonConverterLock = new object(); + private JsonSerializerSettings _serializationSettings; + + public void AddLogType(string typeName, Type type) + { + lock (_jsonConverterLock) + { + _logTypes[typeName] = type; + } + + _serializationSettings = new JsonSerializerSettings + { + Formatting = Formatting.Indented, + DateFormatHandling = DateFormatHandling.IsoDateFormat, + DateTimeZoneHandling = DateTimeZoneHandling.Utc, + NullValueHandling = NullValueHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Serialize, + }; + } + + public override bool CanConvert(Type objectType) + { + return typeof(Log).IsAssignableFrom(objectType); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + lock (_jsonConverterLock) + { + var jsonObject = JObject.Load(reader); + var typeName = jsonObject.GetValue(LogSerializer.TypeIdKey)?.ToString(); + if (typeName == null || !_logTypes.ContainsKey(typeName)) + { + throw new JsonReaderException("Could not identify type of log"); + } + jsonObject.Remove(LogSerializer.TypeIdKey); + return JsonConvert.DeserializeObject(jsonObject.ToString(), _logTypes[typeName], _serializationSettings) as Log; + } + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var info = value.GetType().GetTypeInfo(); + var attribute = info.GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute; + if (attribute == null) + { + throw new JsonWriterException("Cannot deserialize log; missing JsonObjectAttribute"); + } + + var jsonText = JsonConvert.SerializeObject(value, _serializationSettings); + var jsonObject = JObject.Parse(jsonText); + jsonObject.Add(LogSerializer.TypeIdKey, JToken.FromObject(attribute.Id)); + writer.WriteRawValue(jsonObject.ToString()); + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogSerializer.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogSerializer.cs new file mode 100644 index 000000000..a21b5ca43 --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogSerializer.cs @@ -0,0 +1,47 @@ +using Newtonsoft.Json; +using System; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + public static class LogSerializer + { + private static readonly JsonSerializerSettings SerializationSettings; + internal const string TypeIdKey = "type"; + private static readonly LogJsonConverter Converter = new LogJsonConverter(); + + static LogSerializer() + { + SerializationSettings = new JsonSerializerSettings + { + + Formatting = Formatting.Indented, + DateFormatHandling = DateFormatHandling.IsoDateFormat, + DateTimeZoneHandling = DateTimeZoneHandling.Utc, + NullValueHandling = NullValueHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Serialize, + Converters = { Converter } + }; + } + + public static void AddLogType(string typeName, Type type) + { + Converter.AddLogType(typeName, type); + } + + public static string Serialize(LogContainer logContainer) + { + return JsonConvert.SerializeObject(logContainer, SerializationSettings); + } + + public static string Serialize(Log log) + { + return JsonConvert.SerializeObject(log, SerializationSettings); + + } + + public static Log DeserializeLog(string json) + { + return JsonConvert.DeserializeObject(json, SerializationSettings); + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogWithProperties.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogWithProperties.cs new file mode 100644 index 000000000..9706000ce --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogWithProperties.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + public abstract class LogWithProperties : Log + { + /// + /// Initializes a new instance of the LogWithProperties class. + /// + protected LogWithProperties() { } + + /// + /// Initializes a new instance of the LogWithProperties class. + /// + /// Corresponds to the number of milliseconds + /// elapsed between the time the request is sent and the time the log + /// is emitted. + /// When tracking an analytics session, logs can be + /// part of the session by specifying this identifier. + /// This attribute is optional, a missing value means the session + /// tracking is disabled (like when using only error reporting + /// feature). + /// Concrete types like StartSessionLog or PageLog are always part of a + /// session and always include this identifier. + /// + /// Additional key/value pair parameters. + /// + ///Description of the device emitting the log + protected LogWithProperties(long toffset, Device device, System.Guid? sid = default(System.Guid?), IDictionary properties = default(IDictionary)) + : base(toffset, device, sid) + { + Properties = properties; + } + + /// + /// Gets or sets additional key/value pair parameters. + /// + /// + [JsonProperty(PropertyName = "properties")] + public IDictionary Properties { get; set; } + } +} + diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/StartServiceLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/StartServiceLog.cs new file mode 100644 index 000000000..e1428e75f --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/StartServiceLog.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + /// + /// Log type for sending information about which services have been started + /// + [JsonObject(JsonIdentifier)] + public class StartServiceLog : Log + { + internal const string JsonIdentifier = "start_service"; + + /// + /// Initializes a new instance of the Log class. + /// + public StartServiceLog() + { + Services = new List(); + } + + /// + /// Initializes a new instance of the Log class + /// + /// >Corresponds to the number of milliseconds + /// elapsed between the time the request is sent and the time the log + /// is emitted. + /// Device and SDK information + /// Names of services which started with SDK + /// When tracking an analytics session, logs can be + /// part of the session by specifying this identifier. + /// This attribute is optional, a missing value means the session + /// tracking is disabled (like when using only error reporting + /// feature). + /// Concrete types like StartSessionLog or PageLog are always part of a + /// session and always include this identifier. + public StartServiceLog(long toffset, Device device, IEnumerable services, System.Guid? sid = default(System.Guid?)) + : base(toffset, device, sid) + { + Services = new List(services); + } + + /// + /// Services names which have been started + /// + [JsonProperty(PropertyName = "services")] + public List Services { get; set; } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public override void Validate() + { + base.Validate(); + + if (Services == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Services)); + } + } + } +} From 3257fa487a4636b1ed949d288dca68b990a08efd Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Tue, 23 May 2017 14:04:37 +0300 Subject: [PATCH 14/90] Fix StatefulMutex --- .../Utils/Synchronization/StatefulMutex.cs | 23 +++++++++++++------ .../Channel/ChannelGroupTest.cs | 2 +- .../Channel/ChannelTest.cs | 8 +++---- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs index 7f740566b..fb2f188be 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs @@ -45,10 +45,19 @@ public bool IsCurrent(State state) return _state.Equals(state); } - public Task ShutdownAsync(TimeSpan timeout) + public async Task ShutdownAsync() { + await _mutex.WaitAsync().ConfigureAwait(false); _isShutdown = true; - return _mutex.WaitAsync(timeout); + _mutex.Release(); + } + + public async Task ShutdownAsync(TimeSpan timeout) + { + var result = await _mutex.WaitAsync(timeout).ConfigureAwait(false); + _isShutdown = true; + _mutex.Release(); + return result; } /// @@ -57,11 +66,11 @@ public Task ShutdownAsync(TimeSpan timeout) /// public void Lock() { + _mutex.Wait(); if (_isShutdown) { throw new StatefulMutexException(ShutdownExceptionMessage); } - _mutex.Wait(); } /// @@ -72,11 +81,11 @@ public void Lock() /// public void Lock(State stateSnapshot) { + _mutex.Wait(); if (_isShutdown) { throw new StatefulMutexException(ShutdownExceptionMessage); } - _mutex.Wait(); if (!IsCurrent(stateSnapshot)) { throw new StatefulMutexException(StateExceptionMessage); @@ -87,13 +96,13 @@ public void Lock(State stateSnapshot) /// Asynchronously locks the mutex and does not verify any state /// /// - public Task LockAsync() + public async Task LockAsync() { + await _mutex.WaitAsync().ConfigureAwait(false); if (_isShutdown) { throw new StatefulMutexException(ShutdownExceptionMessage); } - return _mutex.WaitAsync(); } /// @@ -104,11 +113,11 @@ public Task LockAsync() /// public async Task LockAsync(State stateSnapshot) { + await _mutex.WaitAsync().ConfigureAwait(false); if (_isShutdown) { throw new StatefulMutexException(ShutdownExceptionMessage); } - await _mutex.WaitAsync().ConfigureAwait(false); if (!IsCurrent(stateSnapshot)) { Unlock(); diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelGroupTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelGroupTest.cs index 74dce266a..b03faa767 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelGroupTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelGroupTest.cs @@ -175,7 +175,7 @@ public void TestShutdownChannelGroup() var addedChannel = _channelGroup.AddChannel(channelName, 2, TimeSpan.FromSeconds(3), 3) as Mobile.Channel.Channel; - _channelGroup.ShutdownAsync(); + _channelGroup.ShutdownAsync().RunNotAsync(); Assert.IsFalse(addedChannel.IsEnabled); } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs index e8589bf09..a6b159cb3 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs @@ -59,7 +59,7 @@ public void ChannelEnabledByDefault() [TestMethod] public void DisableChannel() { - _channel.SetEnabledAsync(false); + _channel.SetEnabledAsync(false).RunNotAsync(); Assert.IsFalse(_channel.IsEnabled); } @@ -70,8 +70,8 @@ public void DisableChannel() [TestMethod] public void EnableChannel() { - _channel.SetEnabledAsync(false); - _channel.SetEnabledAsync(true); + _channel.SetEnabledAsync(false).RunNotAsync(); + _channel.SetEnabledAsync(true).RunNotAsync(); Assert.IsTrue(_channel.IsEnabled); } @@ -237,7 +237,7 @@ public void ThrowStorageExceptionInDeleteLogsTime() Mobile.Channel.Channel channel = new Mobile.Channel.Channel("name", 1, _batchTimeSpan, 1, _appSecret, _mockIngestion, storage.Object); - //Shutdown channel and store some log + // Shutdown channel and store some log channel.ShutdownAsync().RunNotAsync(); channel.EnqueueAsync(new TestLog()).RunNotAsync(); From 54de9d7f723505cb043b697e5e7733fcd48e1d52 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 23 May 2017 09:14:33 -0700 Subject: [PATCH 15/90] Clean up serialization logic and move models folder back to correct location --- .../Http/Models/CustomPropertiesLog.cs | 176 ---------- .../Ingestion/Http/Models/Device.cs | 326 ------------------ .../Ingestion/Http/Models/Log.cs | 78 ----- .../Ingestion/Http/Models/LogContainer.cs | 52 --- .../Ingestion/Http/Models/LogJsonConverter.cs | 67 ---- .../Ingestion/Http/Models/LogSerializer.cs | 47 --- .../Http/Models/LogWithProperties.cs | 46 --- .../Ingestion/Http/Models/StartServiceLog.cs | 65 ---- 8 files changed, 857 deletions(-) delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/CustomPropertiesLog.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Device.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Log.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogContainer.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogJsonConverter.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogSerializer.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogWithProperties.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/StartServiceLog.cs diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/CustomPropertiesLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/CustomPropertiesLog.cs deleted file mode 100644 index 9f81a971d..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/CustomPropertiesLog.cs +++ /dev/null @@ -1,176 +0,0 @@ -using System; -using System.Collections.Generic; -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - /// - /// The custom properties log model. - /// - [JsonObject(JsonIdentifier)] - public class CustomPropertiesLog : Log - { - internal const string JsonIdentifier = "custom_properties"; - private const string PropertyType = "type"; - private const string PropertyName = "name"; - private const string PropertyValue = "value"; - private const string PropertyTypeClear = "clear"; - private const string PropertyTypeBoolean = "boolean"; - private const string PropertyTypeNumber = "number"; - private const string PropertyTypeDatetime = "date_time"; - private const string PropertyTypeString = "string"; - - /// - /// Initializes a new instance of the Log class. - /// - public CustomPropertiesLog() - { - Properties = new Dictionary(); - } - - /// - /// Key/value pair properties. - /// - /// JsonConverter attribute not supported here. - [JsonIgnore] - public IDictionary Properties { get; set; } - - [JsonProperty(PropertyName = "properties")] - internal JArray JsonProperties - { - get { return WriteProperties(Properties); } - set { Properties = ReadProperties(value); } - } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public override void Validate() - { - base.Validate(); - - if (Properties == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Properties)); - } - } - - private static JArray WriteProperties(IDictionary value) - { - if (value == null) - { - return null; - } - var properties = new JArray(); - foreach (var property in value) - { - properties.Add(WriteProperty(property.Key, property.Value)); - } - return properties; - } - - private static JObject WriteProperty(string key, object value) - { - var property = new JObject(); - property.Add(PropertyName, key); - if (value == null) - { - property.Add(PropertyType, PropertyTypeClear); - } - else - { - var typeCode = Convert.GetTypeCode(value); - switch (typeCode) - { - case TypeCode.Boolean: - property.Add(PropertyType, PropertyTypeBoolean); - property.Add(PropertyValue, JToken.FromObject(value)); - break; - case TypeCode.Char: - case TypeCode.String: - property.Add(PropertyType, PropertyTypeString); - property.Add(PropertyValue, JToken.FromObject(value)); - break; - case TypeCode.SByte: - case TypeCode.Byte: - case TypeCode.Int16: - case TypeCode.UInt16: - case TypeCode.Int32: - case TypeCode.UInt32: - case TypeCode.Int64: - case TypeCode.UInt64: - case TypeCode.Single: - case TypeCode.Double: - case TypeCode.Decimal: - property.Add(PropertyType, PropertyTypeNumber); - property.Add(PropertyValue, JToken.FromObject(value)); - break; - case TypeCode.DateTime: - property.Add(PropertyType, PropertyTypeDatetime); - property.Add(PropertyValue, JToken.FromObject(value)); - break; - default: - throw new JsonException("Invalid value type"); - } - } - return property; - } - - private static IDictionary ReadProperties(JArray value) - { - if (value == null) - { - return null; - } - var properties = new Dictionary(); - foreach (var property in value.Children()) - { - var pair = ReadProperty((JObject)property); - properties.Add(pair.Key, pair.Value); - } - return properties; - } - - private static KeyValuePair ReadProperty(JObject property) - { - string type = property.Value(PropertyType); - string name = property.Value(PropertyName); - object value; - switch (type) - { - case PropertyTypeClear: - value = null; - break; - case PropertyTypeBoolean: - value = property.Value(PropertyValue); - break; - case PropertyTypeNumber: - switch (property.GetValue(PropertyValue).Type) - { - case JTokenType.Integer: - value = property.Value(PropertyValue); - break; - case JTokenType.Float: - value = property.Value(PropertyValue); - break; - default: - throw new JsonException("Invalid value type"); - } - break; - case PropertyTypeDatetime: - value = property.Value(PropertyValue); - break; - case PropertyTypeString: - value = property.Value(PropertyValue); - break; - default: - throw new JsonException("Invalid value type"); - } - return new KeyValuePair(name, value); - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Device.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Device.cs deleted file mode 100644 index 6183efb01..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Device.cs +++ /dev/null @@ -1,326 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using Newtonsoft.Json; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - /// - /// Device characteristics. - /// - public class Device - { - /// - /// Initializes a new instance of the Device class. - /// - public Device() { } - - /// - /// Initializes a new instance of the Device class. - /// - /// Name of the SDK. Consists of the name of the - /// SDK and the platform, e.g. "mobilecenter.ios", "hockeysdk.android". - /// - /// Version of the SDK in semver format, e.g. - /// "1.2.0" or "0.12.3-alpha.1". - /// - /// Device model (example: iPad2,3). - /// - /// Device manufacturer (example: HTC). - /// - /// OS name (example: iOS). The following OS names - /// are standardized (non-exclusive): Android, iOS, macOS, tvOS, - /// Windows. - /// - /// OS version (example: 9.3.0). - /// - /// Language code (example: en_US). - /// - /// The offset in minutes from UTC for the - /// device time zone, including daylight savings time. - /// - /// Screen size of the device in pixels - /// (example: 640x480). - /// - /// Application version name, e.g. 1.1.0 - /// - /// The app's build number, e.g. 42. - /// - /// Version of the wrapper SDK in - /// semver format. When the SDK is embedding another base SDK (for - /// example Xamarin.Android wraps Android), the Xamarin specific - /// version is populated into this field while sdkVersion refers to the - /// original Android SDK. - /// - /// Name of the wrapper SDK. Consists of - /// the name of the SDK and the wrapper platform, e.g. - /// "mobilecenter.xamarin", "hockeysdk.cordova". - /// - /// OS build code (example: LMY47X). - /// - /// API level when applicable like in Android - /// (example: 15). - /// - /// Carrier name (for mobile devices). - /// - /// Carrier country code (for mobile - /// devices). - /// - /// The bundle identifier, package - /// identifier, or namespace, depending on what the individual - /// plattforms use, .e.g com.microsoft.example. - /// - /// Label that is used to identify - /// application code 'version' released via Live Update beacon running - /// on device - /// - /// Identifier of environment - /// that current application release belongs to, deployment key then - /// maps to environment like Production, Staging. - /// - /// Hash of all files (ReactNative - /// or Cordova) deployed to device via LiveUpdate beacon. Helps - /// identify the Release version on device or need to download updates - /// in future - /// - public Device(string sdkName, string sdkVersion, string model, string oemName, string osName, string osVersion, string locale, int timeZoneOffset, string screenSize, string appVersion, string appBuild, string wrapperSdkVersion = default(string), string wrapperSdkName = default(string), string osBuild = default(string), int? osApiLevel = default(int?), string carrierName = default(string), string carrierCountry = default(string), string appNamespace = default(string), string liveUpdateReleaseLabel = default(string), string liveUpdateDeploymentKey = default(string), string liveUpdatePackageHash = default(string)) - { - SdkName = sdkName; - SdkVersion = sdkVersion; - WrapperSdkVersion = wrapperSdkVersion; - WrapperSdkName = wrapperSdkName; - Model = model; - OemName = oemName; - OsName = osName; - OsVersion = osVersion; - OsBuild = osBuild; - OsApiLevel = osApiLevel; - Locale = locale; - TimeZoneOffset = timeZoneOffset; - ScreenSize = screenSize; - AppVersion = appVersion; - CarrierName = carrierName; - CarrierCountry = carrierCountry; - AppBuild = appBuild; - AppNamespace = appNamespace; - LiveUpdateReleaseLabel = liveUpdateReleaseLabel; - LiveUpdateDeploymentKey = liveUpdateDeploymentKey; - LiveUpdatePackageHash = liveUpdatePackageHash; - } - - /// - /// Gets or sets name of the SDK. Consists of the name of the SDK and - /// the platform, e.g. "mobilecenter.ios", "hockeysdk.android". - /// - /// - [JsonProperty(PropertyName = "sdk_name")] - public string SdkName { get; set; } - - /// - /// Gets or sets version of the SDK in semver format, e.g. "1.2.0" or - /// "0.12.3-alpha.1". - /// - /// - [JsonProperty(PropertyName = "sdk_version")] - public string SdkVersion { get; set; } - - /// - /// Gets or sets version of the wrapper SDK in semver format. When the - /// SDK is embedding another base SDK (for example Xamarin.Android - /// wraps Android), the Xamarin specific version is populated into this - /// field while sdkVersion refers to the original Android SDK. - /// - /// - [JsonProperty(PropertyName = "wrapper_sdk_version")] - public string WrapperSdkVersion { get; set; } - - /// - /// Gets or sets name of the wrapper SDK. Consists of the name of the - /// SDK and the wrapper platform, e.g. "mobilecenter.xamarin", - /// "hockeysdk.cordova". - /// - /// - [JsonProperty(PropertyName = "wrapper_sdk_name")] - public string WrapperSdkName { get; set; } - - /// - /// Gets or sets device model (example: iPad2,3). - /// - /// - [JsonProperty(PropertyName = "model")] - public string Model { get; set; } - - /// - /// Gets or sets device manufacturer (example: HTC). - /// - /// - [JsonProperty(PropertyName = "oem_name")] - public string OemName { get; set; } - - /// - /// Gets or sets OS name (example: iOS). The following OS names are - /// standardized (non-exclusive): Android, iOS, macOS, tvOS, Windows. - /// - /// - [JsonProperty(PropertyName = "os_name")] - public string OsName { get; set; } - - /// - /// Gets or sets OS version (example: 9.3.0). - /// - /// - [JsonProperty(PropertyName = "os_version")] - public string OsVersion { get; set; } - - /// - /// Gets or sets OS build code (example: LMY47X). - /// - /// - [JsonProperty(PropertyName = "os_build")] - public string OsBuild { get; set; } - - /// - /// Gets or sets API level when applicable like in Android (example: - /// 15). - /// - /// - [JsonProperty(PropertyName = "os_api_level")] - public int? OsApiLevel { get; set; } - - /// - /// Gets or sets language code (example: en_US). - /// - /// - [JsonProperty(PropertyName = "locale")] - public string Locale { get; set; } - - /// - /// Gets or sets the offset in minutes from UTC for the device time - /// zone, including daylight savings time. - /// - /// - [JsonProperty(PropertyName = "time_zone_offset")] - public int TimeZoneOffset { get; set; } - - /// - /// Gets or sets screen size of the device in pixels (example: - /// 640x480). - /// - /// - [JsonProperty(PropertyName = "screen_size")] - public string ScreenSize { get; set; } - - /// - /// Gets or sets application version name, e.g. 1.1.0 - /// - /// - [JsonProperty(PropertyName = "app_version")] - public string AppVersion { get; set; } - - /// - /// Gets or sets carrier name (for mobile devices). - /// - /// - [JsonProperty(PropertyName = "carrier_name")] - public string CarrierName { get; set; } - - /// - /// Gets or sets carrier country code (for mobile devices). - /// - /// - [JsonProperty(PropertyName = "carrier_country")] - public string CarrierCountry { get; set; } - - /// - /// Gets or sets the app's build number, e.g. 42. - /// - /// - [JsonProperty(PropertyName = "app_build")] - public string AppBuild { get; set; } - - /// - /// Gets or sets the bundle identifier, package identifier, or - /// namespace, depending on what the individual plattforms use, .e.g - /// com.microsoft.example. - /// - /// - [JsonProperty(PropertyName = "app_namespace")] - public string AppNamespace { get; set; } - - /// - /// Gets or sets label that is used to identify application code - /// 'version' released via Live Update beacon running on device - /// - /// - [JsonProperty(PropertyName = "live_update_release_label")] - public string LiveUpdateReleaseLabel { get; set; } - - /// - /// Gets or sets identifier of environment that current application - /// release belongs to, deployment key then maps to environment like - /// Production, Staging. - /// - /// - [JsonProperty(PropertyName = "live_update_deployment_key")] - public string LiveUpdateDeploymentKey { get; set; } - - /// - /// Gets or sets hash of all files (ReactNative or Cordova) deployed to - /// device via LiveUpdate beacon. Helps identify the Release version on - /// device or need to download updates in future - /// - /// - [JsonProperty(PropertyName = "live_update_package_hash")] - public string LiveUpdatePackageHash { get; set; } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public virtual void Validate() - { - if (SdkName == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkName"); - } - if (SdkVersion == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkVersion"); - } - if (Model == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Model"); - } - if (OemName == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OemName"); - } - if (OsName == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsName"); - } - if (OsVersion == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsVersion"); - } - if (Locale == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Locale"); - } - if (ScreenSize == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "ScreenSize"); - } - if (AppVersion == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppVersion"); - } - if (AppBuild == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppBuild"); - } - } - } -} - diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Log.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Log.cs deleted file mode 100644 index b3c160032..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/Log.cs +++ /dev/null @@ -1,78 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using Newtonsoft.Json; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public abstract class Log - { - /// - /// Initializes a new instance of the Log class. - /// - protected Log() { } - - /// - /// Initializes a new instance of the Log class. - /// - /// Corresponds to the number of milliseconds - /// elapsed between the time the request is sent and the time the log - /// is emitted. - /// When tracking an analytics session, logs can be - /// part of the session by specifying this identifier. - /// This attribute is optional, a missing value means the session - /// tracking is disabled (like when using only error reporting - /// feature). - /// Concrete types like StartSessionLog or PageLog are always part of a - /// session and always include this identifier. - /// - /// Description of the device emitting the log - protected Log(long toffset, Device device, System.Guid? sid = default(System.Guid?)) - { - Toffset = toffset; - Sid = sid; - Device = device; - } - - /// - /// Gets or sets corresponds to the number of milliseconds elapsed - /// between the time the request is sent and the time the log is - /// emitted. - /// - [JsonProperty(PropertyName = "toffset")] - public long Toffset { get; set; } - - /// - /// Gets or sets when tracking an analytics session, logs can be part - /// of the session by specifying this identifier. - /// This attribute is optional, a missing value means the session - /// tracking is disabled (like when using only error reporting - /// feature). - /// Concrete types like StartSessionLog or PageLog are always part of a - /// session and always include this identifier. - /// - /// - [JsonProperty(PropertyName = "sid")] - public System.Guid? Sid { get; set; } - - /// - /// - [JsonProperty(PropertyName = "device")] - public Device Device { get; set; } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public virtual void Validate() - { - if (Device == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Device"); - } - Device.Validate(); - } - } -} - diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogContainer.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogContainer.cs deleted file mode 100644 index dd81f648d..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogContainer.cs +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using Newtonsoft.Json; -using System.Collections.Generic; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public class LogContainer - { - /// - /// Initializes a new instance of the LogContainer class. - /// - public LogContainer() { } - - /// - /// Initializes a new instance of the LogContainer class. - /// - /// The list of logs - public LogContainer(IList logs) - { - Logs = logs; - } - - /// - /// Gets or sets the list of logs - /// - [JsonProperty(PropertyName = "logs")] - public IList Logs { get; set; } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public virtual void Validate() - { - if (Logs == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Logs"); - } - if (Logs.Count < 1) - { - throw new Rest.ValidationException(Rest.ValidationRules.MinItems, "Logs", 1); - } - foreach (var element in Logs) - { - element?.Validate(); - } - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogJsonConverter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogJsonConverter.cs deleted file mode 100644 index 457c11cc9..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogJsonConverter.cs +++ /dev/null @@ -1,67 +0,0 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.Reflection; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public class LogJsonConverter : JsonConverter - { - private readonly Dictionary _logTypes = new Dictionary(); - private readonly object _jsonConverterLock = new object(); - private JsonSerializerSettings _serializationSettings; - - public void AddLogType(string typeName, Type type) - { - lock (_jsonConverterLock) - { - _logTypes[typeName] = type; - } - - _serializationSettings = new JsonSerializerSettings - { - Formatting = Formatting.Indented, - DateFormatHandling = DateFormatHandling.IsoDateFormat, - DateTimeZoneHandling = DateTimeZoneHandling.Utc, - NullValueHandling = NullValueHandling.Ignore, - ReferenceLoopHandling = ReferenceLoopHandling.Serialize, - }; - } - - public override bool CanConvert(Type objectType) - { - return typeof(Log).IsAssignableFrom(objectType); - } - - public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) - { - lock (_jsonConverterLock) - { - var jsonObject = JObject.Load(reader); - var typeName = jsonObject.GetValue(LogSerializer.TypeIdKey)?.ToString(); - if (typeName == null || !_logTypes.ContainsKey(typeName)) - { - throw new JsonReaderException("Could not identify type of log"); - } - jsonObject.Remove(LogSerializer.TypeIdKey); - return JsonConvert.DeserializeObject(jsonObject.ToString(), _logTypes[typeName], _serializationSettings) as Log; - } - } - - public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) - { - var info = value.GetType().GetTypeInfo(); - var attribute = info.GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute; - if (attribute == null) - { - throw new JsonWriterException("Cannot deserialize log; missing JsonObjectAttribute"); - } - - var jsonText = JsonConvert.SerializeObject(value, _serializationSettings); - var jsonObject = JObject.Parse(jsonText); - jsonObject.Add(LogSerializer.TypeIdKey, JToken.FromObject(attribute.Id)); - writer.WriteRawValue(jsonObject.ToString()); - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogSerializer.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogSerializer.cs deleted file mode 100644 index a21b5ca43..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogSerializer.cs +++ /dev/null @@ -1,47 +0,0 @@ -using Newtonsoft.Json; -using System; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public static class LogSerializer - { - private static readonly JsonSerializerSettings SerializationSettings; - internal const string TypeIdKey = "type"; - private static readonly LogJsonConverter Converter = new LogJsonConverter(); - - static LogSerializer() - { - SerializationSettings = new JsonSerializerSettings - { - - Formatting = Formatting.Indented, - DateFormatHandling = DateFormatHandling.IsoDateFormat, - DateTimeZoneHandling = DateTimeZoneHandling.Utc, - NullValueHandling = NullValueHandling.Ignore, - ReferenceLoopHandling = ReferenceLoopHandling.Serialize, - Converters = { Converter } - }; - } - - public static void AddLogType(string typeName, Type type) - { - Converter.AddLogType(typeName, type); - } - - public static string Serialize(LogContainer logContainer) - { - return JsonConvert.SerializeObject(logContainer, SerializationSettings); - } - - public static string Serialize(Log log) - { - return JsonConvert.SerializeObject(log, SerializationSettings); - - } - - public static Log DeserializeLog(string json) - { - return JsonConvert.DeserializeObject(json, SerializationSettings); - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogWithProperties.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogWithProperties.cs deleted file mode 100644 index 9706000ce..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/LogWithProperties.cs +++ /dev/null @@ -1,46 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. - -using Newtonsoft.Json; -using System.Collections.Generic; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - public abstract class LogWithProperties : Log - { - /// - /// Initializes a new instance of the LogWithProperties class. - /// - protected LogWithProperties() { } - - /// - /// Initializes a new instance of the LogWithProperties class. - /// - /// Corresponds to the number of milliseconds - /// elapsed between the time the request is sent and the time the log - /// is emitted. - /// When tracking an analytics session, logs can be - /// part of the session by specifying this identifier. - /// This attribute is optional, a missing value means the session - /// tracking is disabled (like when using only error reporting - /// feature). - /// Concrete types like StartSessionLog or PageLog are always part of a - /// session and always include this identifier. - /// - /// Additional key/value pair parameters. - /// - ///Description of the device emitting the log - protected LogWithProperties(long toffset, Device device, System.Guid? sid = default(System.Guid?), IDictionary properties = default(IDictionary)) - : base(toffset, device, sid) - { - Properties = properties; - } - - /// - /// Gets or sets additional key/value pair parameters. - /// - /// - [JsonProperty(PropertyName = "properties")] - public IDictionary Properties { get; set; } - } -} - diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/StartServiceLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/StartServiceLog.cs deleted file mode 100644 index e1428e75f..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/Models/StartServiceLog.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System.Collections.Generic; -using Newtonsoft.Json; - -namespace Microsoft.Azure.Mobile.Ingestion.Models -{ - /// - /// Log type for sending information about which services have been started - /// - [JsonObject(JsonIdentifier)] - public class StartServiceLog : Log - { - internal const string JsonIdentifier = "start_service"; - - /// - /// Initializes a new instance of the Log class. - /// - public StartServiceLog() - { - Services = new List(); - } - - /// - /// Initializes a new instance of the Log class - /// - /// >Corresponds to the number of milliseconds - /// elapsed between the time the request is sent and the time the log - /// is emitted. - /// Device and SDK information - /// Names of services which started with SDK - /// When tracking an analytics session, logs can be - /// part of the session by specifying this identifier. - /// This attribute is optional, a missing value means the session - /// tracking is disabled (like when using only error reporting - /// feature). - /// Concrete types like StartSessionLog or PageLog are always part of a - /// session and always include this identifier. - public StartServiceLog(long toffset, Device device, IEnumerable services, System.Guid? sid = default(System.Guid?)) - : base(toffset, device, sid) - { - Services = new List(services); - } - - /// - /// Services names which have been started - /// - [JsonProperty(PropertyName = "services")] - public List Services { get; set; } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public override void Validate() - { - base.Validate(); - - if (Services == null) - { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Services)); - } - } - } -} From a21420db02bebc0fba4bde31996cefaca13d268b Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 23 May 2017 09:18:29 -0700 Subject: [PATCH 16/90] Move models to proper location and move serialization to its own namespace --- .../Ingestion/Http/IngestionHttp.cs | 1 + .../Ingestion/Models/CustomPropertiesLog.cs | 177 ++++++++++ .../Ingestion/Models/Device.cs | 326 ++++++++++++++++++ .../Ingestion/Models/Log.cs | 78 +++++ .../Ingestion/Models/LogContainer.cs | 52 +++ .../Ingestion/Models/LogWithProperties.cs | 46 +++ .../Models/Serialization/LogJsonConverter.cs | 73 ++++ .../Models/Serialization/LogSerializer.cs | 46 +++ .../Ingestion/Models/StartServiceLog.cs | 65 ++++ ...soft.Azure.Mobile.Windows.Shared.projitems | 19 +- .../MobileCenter.cs | 9 +- .../Storage/Storage.cs | 5 +- 12 files changed, 882 insertions(+), 15 deletions(-) create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogWithProperties.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Serialization/LogJsonConverter.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Serialization/LogSerializer.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IngestionHttp.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IngestionHttp.cs index 4718753b8..a8cad0732 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IngestionHttp.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Http/IngestionHttp.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Microsoft.Azure.Mobile.Ingestion.Models; using Microsoft.Azure.Mobile.Utils; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; namespace Microsoft.Azure.Mobile.Ingestion.Http { diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs new file mode 100644 index 000000000..c005a891f --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + /// + /// The custom properties log model. + /// + [JsonObject(JsonIdentifier)] + public class CustomPropertiesLog : Log + { + internal const string JsonIdentifier = "custom_properties"; + private const string PropertyType = "type"; + private const string PropertyName = "name"; + private const string PropertyValue = "value"; + private const string PropertyTypeClear = "clear"; + private const string PropertyTypeBoolean = "boolean"; + private const string PropertyTypeNumber = "number"; + private const string PropertyTypeDatetime = "date_time"; + private const string PropertyTypeString = "string"; + + /// + /// Initializes a new instance of the Log class. + /// + public CustomPropertiesLog() + { + Properties = new Dictionary(); + } + + /// + /// Key/value pair properties. + /// + /// JsonConverter attribute not supported here. + [JsonIgnore] + public IDictionary Properties { get; set; } + + [JsonProperty(PropertyName = "properties")] + internal JArray JsonProperties + { + get { return WriteProperties(Properties); } + set { Properties = ReadProperties(value); } + } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public override void Validate() + { + base.Validate(); + + if (Properties == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Properties)); + } + } + + private static JArray WriteProperties(IDictionary value) + { + if (value == null) + { + return null; + } + var properties = new JArray(); + foreach (var property in value) + { + properties.Add(WriteProperty(property.Key, property.Value)); + } + return properties; + } + + private static JObject WriteProperty(string key, object value) + { + var property = new JObject(); + property.Add(PropertyName, key); + if (value == null) + { + property.Add(PropertyType, PropertyTypeClear); + } + else + { + var typeCode = Convert.GetTypeCode(value); + switch (typeCode) + { + case TypeCode.Boolean: + property.Add(PropertyType, PropertyTypeBoolean); + property.Add(PropertyValue, JToken.FromObject(value)); + break; + case TypeCode.Char: + case TypeCode.String: + property.Add(PropertyType, PropertyTypeString); + property.Add(PropertyValue, JToken.FromObject(value)); + break; + case TypeCode.SByte: + case TypeCode.Byte: + case TypeCode.Int16: + case TypeCode.UInt16: + case TypeCode.Int32: + case TypeCode.UInt32: + case TypeCode.Int64: + case TypeCode.UInt64: + case TypeCode.Single: + case TypeCode.Double: + case TypeCode.Decimal: + property.Add(PropertyType, PropertyTypeNumber); + property.Add(PropertyValue, JToken.FromObject(value)); + break; + case TypeCode.DateTime: + property.Add(PropertyType, PropertyTypeDatetime); + property.Add(PropertyValue, JToken.FromObject(value)); + break; + default: + throw new JsonException("Invalid value type"); + } + } + return property; + } + + private static IDictionary ReadProperties(JArray value) + { + if (value == null) + { + return null; + } + var properties = new Dictionary(); + foreach (var property in value.Children()) + { + var pair = ReadProperty((JObject)property); + properties.Add(pair.Key, pair.Value); + } + return properties; + } + + private static KeyValuePair ReadProperty(JObject property) + { + string type = property.Value(PropertyType); + string name = property.Value(PropertyName); + object value; + switch (type) + { + case PropertyTypeClear: + value = null; + break; + case PropertyTypeBoolean: + value = property.Value(PropertyValue); + break; + case PropertyTypeNumber: + switch (property.GetValue(PropertyValue).Type) + { + case JTokenType.Integer: + value = property.Value(PropertyValue); + break; + case JTokenType.Float: + value = property.Value(PropertyValue); + break; + default: + throw new JsonException("Invalid value type"); + } + break; + case PropertyTypeDatetime: + value = property.Value(PropertyValue); + break; + case PropertyTypeString: + value = property.Value(PropertyValue); + break; + default: + throw new JsonException("Invalid value type"); + } + return new KeyValuePair(name, value); + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs new file mode 100644 index 000000000..6183efb01 --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs @@ -0,0 +1,326 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +using Newtonsoft.Json; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + /// + /// Device characteristics. + /// + public class Device + { + /// + /// Initializes a new instance of the Device class. + /// + public Device() { } + + /// + /// Initializes a new instance of the Device class. + /// + /// Name of the SDK. Consists of the name of the + /// SDK and the platform, e.g. "mobilecenter.ios", "hockeysdk.android". + /// + /// Version of the SDK in semver format, e.g. + /// "1.2.0" or "0.12.3-alpha.1". + /// + /// Device model (example: iPad2,3). + /// + /// Device manufacturer (example: HTC). + /// + /// OS name (example: iOS). The following OS names + /// are standardized (non-exclusive): Android, iOS, macOS, tvOS, + /// Windows. + /// + /// OS version (example: 9.3.0). + /// + /// Language code (example: en_US). + /// + /// The offset in minutes from UTC for the + /// device time zone, including daylight savings time. + /// + /// Screen size of the device in pixels + /// (example: 640x480). + /// + /// Application version name, e.g. 1.1.0 + /// + /// The app's build number, e.g. 42. + /// + /// Version of the wrapper SDK in + /// semver format. When the SDK is embedding another base SDK (for + /// example Xamarin.Android wraps Android), the Xamarin specific + /// version is populated into this field while sdkVersion refers to the + /// original Android SDK. + /// + /// Name of the wrapper SDK. Consists of + /// the name of the SDK and the wrapper platform, e.g. + /// "mobilecenter.xamarin", "hockeysdk.cordova". + /// + /// OS build code (example: LMY47X). + /// + /// API level when applicable like in Android + /// (example: 15). + /// + /// Carrier name (for mobile devices). + /// + /// Carrier country code (for mobile + /// devices). + /// + /// The bundle identifier, package + /// identifier, or namespace, depending on what the individual + /// plattforms use, .e.g com.microsoft.example. + /// + /// Label that is used to identify + /// application code 'version' released via Live Update beacon running + /// on device + /// + /// Identifier of environment + /// that current application release belongs to, deployment key then + /// maps to environment like Production, Staging. + /// + /// Hash of all files (ReactNative + /// or Cordova) deployed to device via LiveUpdate beacon. Helps + /// identify the Release version on device or need to download updates + /// in future + /// + public Device(string sdkName, string sdkVersion, string model, string oemName, string osName, string osVersion, string locale, int timeZoneOffset, string screenSize, string appVersion, string appBuild, string wrapperSdkVersion = default(string), string wrapperSdkName = default(string), string osBuild = default(string), int? osApiLevel = default(int?), string carrierName = default(string), string carrierCountry = default(string), string appNamespace = default(string), string liveUpdateReleaseLabel = default(string), string liveUpdateDeploymentKey = default(string), string liveUpdatePackageHash = default(string)) + { + SdkName = sdkName; + SdkVersion = sdkVersion; + WrapperSdkVersion = wrapperSdkVersion; + WrapperSdkName = wrapperSdkName; + Model = model; + OemName = oemName; + OsName = osName; + OsVersion = osVersion; + OsBuild = osBuild; + OsApiLevel = osApiLevel; + Locale = locale; + TimeZoneOffset = timeZoneOffset; + ScreenSize = screenSize; + AppVersion = appVersion; + CarrierName = carrierName; + CarrierCountry = carrierCountry; + AppBuild = appBuild; + AppNamespace = appNamespace; + LiveUpdateReleaseLabel = liveUpdateReleaseLabel; + LiveUpdateDeploymentKey = liveUpdateDeploymentKey; + LiveUpdatePackageHash = liveUpdatePackageHash; + } + + /// + /// Gets or sets name of the SDK. Consists of the name of the SDK and + /// the platform, e.g. "mobilecenter.ios", "hockeysdk.android". + /// + /// + [JsonProperty(PropertyName = "sdk_name")] + public string SdkName { get; set; } + + /// + /// Gets or sets version of the SDK in semver format, e.g. "1.2.0" or + /// "0.12.3-alpha.1". + /// + /// + [JsonProperty(PropertyName = "sdk_version")] + public string SdkVersion { get; set; } + + /// + /// Gets or sets version of the wrapper SDK in semver format. When the + /// SDK is embedding another base SDK (for example Xamarin.Android + /// wraps Android), the Xamarin specific version is populated into this + /// field while sdkVersion refers to the original Android SDK. + /// + /// + [JsonProperty(PropertyName = "wrapper_sdk_version")] + public string WrapperSdkVersion { get; set; } + + /// + /// Gets or sets name of the wrapper SDK. Consists of the name of the + /// SDK and the wrapper platform, e.g. "mobilecenter.xamarin", + /// "hockeysdk.cordova". + /// + /// + [JsonProperty(PropertyName = "wrapper_sdk_name")] + public string WrapperSdkName { get; set; } + + /// + /// Gets or sets device model (example: iPad2,3). + /// + /// + [JsonProperty(PropertyName = "model")] + public string Model { get; set; } + + /// + /// Gets or sets device manufacturer (example: HTC). + /// + /// + [JsonProperty(PropertyName = "oem_name")] + public string OemName { get; set; } + + /// + /// Gets or sets OS name (example: iOS). The following OS names are + /// standardized (non-exclusive): Android, iOS, macOS, tvOS, Windows. + /// + /// + [JsonProperty(PropertyName = "os_name")] + public string OsName { get; set; } + + /// + /// Gets or sets OS version (example: 9.3.0). + /// + /// + [JsonProperty(PropertyName = "os_version")] + public string OsVersion { get; set; } + + /// + /// Gets or sets OS build code (example: LMY47X). + /// + /// + [JsonProperty(PropertyName = "os_build")] + public string OsBuild { get; set; } + + /// + /// Gets or sets API level when applicable like in Android (example: + /// 15). + /// + /// + [JsonProperty(PropertyName = "os_api_level")] + public int? OsApiLevel { get; set; } + + /// + /// Gets or sets language code (example: en_US). + /// + /// + [JsonProperty(PropertyName = "locale")] + public string Locale { get; set; } + + /// + /// Gets or sets the offset in minutes from UTC for the device time + /// zone, including daylight savings time. + /// + /// + [JsonProperty(PropertyName = "time_zone_offset")] + public int TimeZoneOffset { get; set; } + + /// + /// Gets or sets screen size of the device in pixels (example: + /// 640x480). + /// + /// + [JsonProperty(PropertyName = "screen_size")] + public string ScreenSize { get; set; } + + /// + /// Gets or sets application version name, e.g. 1.1.0 + /// + /// + [JsonProperty(PropertyName = "app_version")] + public string AppVersion { get; set; } + + /// + /// Gets or sets carrier name (for mobile devices). + /// + /// + [JsonProperty(PropertyName = "carrier_name")] + public string CarrierName { get; set; } + + /// + /// Gets or sets carrier country code (for mobile devices). + /// + /// + [JsonProperty(PropertyName = "carrier_country")] + public string CarrierCountry { get; set; } + + /// + /// Gets or sets the app's build number, e.g. 42. + /// + /// + [JsonProperty(PropertyName = "app_build")] + public string AppBuild { get; set; } + + /// + /// Gets or sets the bundle identifier, package identifier, or + /// namespace, depending on what the individual plattforms use, .e.g + /// com.microsoft.example. + /// + /// + [JsonProperty(PropertyName = "app_namespace")] + public string AppNamespace { get; set; } + + /// + /// Gets or sets label that is used to identify application code + /// 'version' released via Live Update beacon running on device + /// + /// + [JsonProperty(PropertyName = "live_update_release_label")] + public string LiveUpdateReleaseLabel { get; set; } + + /// + /// Gets or sets identifier of environment that current application + /// release belongs to, deployment key then maps to environment like + /// Production, Staging. + /// + /// + [JsonProperty(PropertyName = "live_update_deployment_key")] + public string LiveUpdateDeploymentKey { get; set; } + + /// + /// Gets or sets hash of all files (ReactNative or Cordova) deployed to + /// device via LiveUpdate beacon. Helps identify the Release version on + /// device or need to download updates in future + /// + /// + [JsonProperty(PropertyName = "live_update_package_hash")] + public string LiveUpdatePackageHash { get; set; } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public virtual void Validate() + { + if (SdkName == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkName"); + } + if (SdkVersion == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkVersion"); + } + if (Model == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Model"); + } + if (OemName == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OemName"); + } + if (OsName == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsName"); + } + if (OsVersion == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsVersion"); + } + if (Locale == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Locale"); + } + if (ScreenSize == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "ScreenSize"); + } + if (AppVersion == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppVersion"); + } + if (AppBuild == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppBuild"); + } + } + } +} + diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs new file mode 100644 index 000000000..b3c160032 --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs @@ -0,0 +1,78 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +using Newtonsoft.Json; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + public abstract class Log + { + /// + /// Initializes a new instance of the Log class. + /// + protected Log() { } + + /// + /// Initializes a new instance of the Log class. + /// + /// Corresponds to the number of milliseconds + /// elapsed between the time the request is sent and the time the log + /// is emitted. + /// When tracking an analytics session, logs can be + /// part of the session by specifying this identifier. + /// This attribute is optional, a missing value means the session + /// tracking is disabled (like when using only error reporting + /// feature). + /// Concrete types like StartSessionLog or PageLog are always part of a + /// session and always include this identifier. + /// + /// Description of the device emitting the log + protected Log(long toffset, Device device, System.Guid? sid = default(System.Guid?)) + { + Toffset = toffset; + Sid = sid; + Device = device; + } + + /// + /// Gets or sets corresponds to the number of milliseconds elapsed + /// between the time the request is sent and the time the log is + /// emitted. + /// + [JsonProperty(PropertyName = "toffset")] + public long Toffset { get; set; } + + /// + /// Gets or sets when tracking an analytics session, logs can be part + /// of the session by specifying this identifier. + /// This attribute is optional, a missing value means the session + /// tracking is disabled (like when using only error reporting + /// feature). + /// Concrete types like StartSessionLog or PageLog are always part of a + /// session and always include this identifier. + /// + /// + [JsonProperty(PropertyName = "sid")] + public System.Guid? Sid { get; set; } + + /// + /// + [JsonProperty(PropertyName = "device")] + public Device Device { get; set; } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public virtual void Validate() + { + if (Device == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Device"); + } + Device.Validate(); + } + } +} + diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs new file mode 100644 index 000000000..dd81f648d --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + public class LogContainer + { + /// + /// Initializes a new instance of the LogContainer class. + /// + public LogContainer() { } + + /// + /// Initializes a new instance of the LogContainer class. + /// + /// The list of logs + public LogContainer(IList logs) + { + Logs = logs; + } + + /// + /// Gets or sets the list of logs + /// + [JsonProperty(PropertyName = "logs")] + public IList Logs { get; set; } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public virtual void Validate() + { + if (Logs == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Logs"); + } + if (Logs.Count < 1) + { + throw new Rest.ValidationException(Rest.ValidationRules.MinItems, "Logs", 1); + } + foreach (var element in Logs) + { + element?.Validate(); + } + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogWithProperties.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogWithProperties.cs new file mode 100644 index 000000000..9706000ce --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogWithProperties.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. + +using Newtonsoft.Json; +using System.Collections.Generic; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + public abstract class LogWithProperties : Log + { + /// + /// Initializes a new instance of the LogWithProperties class. + /// + protected LogWithProperties() { } + + /// + /// Initializes a new instance of the LogWithProperties class. + /// + /// Corresponds to the number of milliseconds + /// elapsed between the time the request is sent and the time the log + /// is emitted. + /// When tracking an analytics session, logs can be + /// part of the session by specifying this identifier. + /// This attribute is optional, a missing value means the session + /// tracking is disabled (like when using only error reporting + /// feature). + /// Concrete types like StartSessionLog or PageLog are always part of a + /// session and always include this identifier. + /// + /// Additional key/value pair parameters. + /// + ///Description of the device emitting the log + protected LogWithProperties(long toffset, Device device, System.Guid? sid = default(System.Guid?), IDictionary properties = default(IDictionary)) + : base(toffset, device, sid) + { + Properties = properties; + } + + /// + /// Gets or sets additional key/value pair parameters. + /// + /// + [JsonProperty(PropertyName = "properties")] + public IDictionary Properties { get; set; } + } +} + diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Serialization/LogJsonConverter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Serialization/LogJsonConverter.cs new file mode 100644 index 000000000..a8703519c --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Serialization/LogJsonConverter.cs @@ -0,0 +1,73 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.Reflection; + +namespace Microsoft.Azure.Mobile.Ingestion.Models.Serialization +{ + public class LogJsonConverter : JsonConverter + { + private readonly Dictionary _logTypes = new Dictionary(); + private readonly object _jsonConverterLock = new object(); + private static readonly JsonSerializerSettings SerializationSettings; + internal const string TypeIdKey = "type"; + + static LogJsonConverter() + { + SerializationSettings = new JsonSerializerSettings + { + Formatting = Formatting.Indented, + DateFormatHandling = DateFormatHandling.IsoDateFormat, + DateTimeZoneHandling = DateTimeZoneHandling.Utc, + NullValueHandling = NullValueHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Serialize + }; + } + + public void AddLogType(string typeName, Type type) + { + lock (_jsonConverterLock) + { + _logTypes[typeName] = type; + } + } + + public override bool CanConvert(Type objectType) + { + return typeof(Log).IsAssignableFrom(objectType); + } + + public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) + { + Type logType; + var jsonObject = JObject.Load(reader); + var typeName = jsonObject.GetValue(TypeIdKey)?.ToString(); + lock (_jsonConverterLock) + { + if (typeName == null || !_logTypes.ContainsKey(typeName)) + { + throw new JsonReaderException("Could not identify type of log"); + } + logType = _logTypes[typeName]; + } + jsonObject.Remove(TypeIdKey); + return jsonObject.ToObject(logType); + } + + public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) + { + var info = value.GetType().GetTypeInfo(); + var attribute = info.GetCustomAttribute(typeof(JsonObjectAttribute)) as JsonObjectAttribute; + if (attribute == null) + { + throw new JsonWriterException("Cannot serialize log; Log type is missing JsonObjectAttribute"); + } + + var jsonText = JsonConvert.SerializeObject(value, SerializationSettings); + var jsonObject = JObject.Parse(jsonText); + jsonObject.Add(TypeIdKey, JToken.FromObject(attribute.Id)); + writer.WriteRawValue(jsonObject.ToString()); + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Serialization/LogSerializer.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Serialization/LogSerializer.cs new file mode 100644 index 000000000..bccdd04b3 --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Serialization/LogSerializer.cs @@ -0,0 +1,46 @@ +using Newtonsoft.Json; +using System; + +namespace Microsoft.Azure.Mobile.Ingestion.Models.Serialization +{ + public static class LogSerializer + { + private static readonly JsonSerializerSettings SerializationSettings; + private static readonly LogJsonConverter Converter = new LogJsonConverter(); + + static LogSerializer() + { + SerializationSettings = new JsonSerializerSettings + { + + Formatting = Formatting.Indented, + DateFormatHandling = DateFormatHandling.IsoDateFormat, + DateTimeZoneHandling = DateTimeZoneHandling.Utc, + NullValueHandling = NullValueHandling.Ignore, + ReferenceLoopHandling = ReferenceLoopHandling.Serialize, + Converters = { Converter } + }; + } + + public static void AddLogType(string typeName, Type type) + { + Converter.AddLogType(typeName, type); + } + + public static string Serialize(LogContainer logContainer) + { + return JsonConvert.SerializeObject(logContainer, SerializationSettings); + } + + public static string Serialize(Log log) + { + return JsonConvert.SerializeObject(log, SerializationSettings); + + } + + public static Log DeserializeLog(string json) + { + return JsonConvert.DeserializeObject(json, SerializationSettings); + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs new file mode 100644 index 000000000..e1428e75f --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs @@ -0,0 +1,65 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + /// + /// Log type for sending information about which services have been started + /// + [JsonObject(JsonIdentifier)] + public class StartServiceLog : Log + { + internal const string JsonIdentifier = "start_service"; + + /// + /// Initializes a new instance of the Log class. + /// + public StartServiceLog() + { + Services = new List(); + } + + /// + /// Initializes a new instance of the Log class + /// + /// >Corresponds to the number of milliseconds + /// elapsed between the time the request is sent and the time the log + /// is emitted. + /// Device and SDK information + /// Names of services which started with SDK + /// When tracking an analytics session, logs can be + /// part of the session by specifying this identifier. + /// This attribute is optional, a missing value means the session + /// tracking is disabled (like when using only error reporting + /// feature). + /// Concrete types like StartSessionLog or PageLog are always part of a + /// session and always include this identifier. + public StartServiceLog(long toffset, Device device, IEnumerable services, System.Guid? sid = default(System.Guid?)) + : base(toffset, device, sid) + { + Services = new List(services); + } + + /// + /// Services names which have been started + /// + [JsonProperty(PropertyName = "services")] + public List Services { get; set; } + + /// + /// Validate the object. + /// + /// + /// Thrown if validation fails + /// + public override void Validate() + { + base.Validate(); + + if (Services == null) + { + throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Services)); + } + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems index 0cb9ae922..2cb94724e 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems @@ -21,7 +21,7 @@ - + @@ -34,7 +34,7 @@ - + @@ -43,12 +43,12 @@ - - - - - - + + + + + + @@ -66,4 +66,7 @@ + + + \ No newline at end of file diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs index 44c13dc52..cc36378f3 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs @@ -1,9 +1,10 @@ -using Microsoft.Azure.Mobile.Channel; -using Microsoft.Azure.Mobile.Ingestion.Models; -using Microsoft.Azure.Mobile.Utils; -using System; +using System; using System.Collections.Generic; using System.Reflection; +using Microsoft.Azure.Mobile.Channel; +using Microsoft.Azure.Mobile.Ingestion.Models; +using Microsoft.Azure.Mobile.Utils; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; namespace Microsoft.Azure.Mobile { diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs index 9398487af..48f09d950 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs @@ -1,11 +1,10 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Threading.Tasks; -using System.Threading; using Newtonsoft.Json; -using Microsoft.Azure.Mobile.Ingestion.Models; using SQLite; +using Microsoft.Azure.Mobile.Ingestion.Models; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; namespace Microsoft.Azure.Mobile.Storage { From e9f8f37e121e08154d889472a58ba9fe867f1811 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 23 May 2017 09:53:05 -0700 Subject: [PATCH 17/90] Replace Rest.ValidationException --- .../Ingestion/Models/CustomPropertiesLog.cs | 5 ++-- .../Ingestion/Models/Device.cs | 23 +++++++++---------- .../Ingestion/Models/Log.cs | 4 ++-- .../Ingestion/Models/LogContainer.cs | 8 +++---- .../Ingestion/Models/StartServiceLog.cs | 4 ++-- ...soft.Azure.Mobile.Windows.Shared.projitems | 1 + .../Analytics.cs | 2 +- .../Push.cs | 2 +- .../Microsoft.Azure.Mobile.NET.csproj | 3 --- .../packages.config | 1 - .../Models/PushInstallationLogTest.cs | 4 ++-- .../Channel/ChannelTest.cs | 1 + .../Models/CustomPropertiesLogTest.cs | 1 + .../Ingestion/Models/JsonLogConverterTest.cs | 4 ++-- .../Ingestion/Models/LogContainerTest.cs | 1 - .../Ingestion/Models/LogTest.cs | 1 - .../Ingestion/Models/StartServiceLogTest.cs | 1 + .../TestLog.cs | 1 + 18 files changed, 32 insertions(+), 35 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs index c005a891f..75a3849d3 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/CustomPropertiesLog.cs @@ -2,7 +2,6 @@ using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; -using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; namespace Microsoft.Azure.Mobile.Ingestion.Models { @@ -47,7 +46,7 @@ internal JArray JsonProperties /// /// Validate the object. /// - /// + /// /// Thrown if validation fails /// public override void Validate() @@ -56,7 +55,7 @@ public override void Validate() if (Properties == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Properties)); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(Properties)); } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs index 6183efb01..b62d5eb98 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Device.cs @@ -1,5 +1,4 @@ // Copyright (c) Microsoft Corporation. All rights reserved. - using Newtonsoft.Json; namespace Microsoft.Azure.Mobile.Ingestion.Models @@ -275,50 +274,50 @@ public Device() { } /// /// Validate the object. /// - /// + /// /// Thrown if validation fails /// public virtual void Validate() { if (SdkName == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkName"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(SdkName)); } if (SdkVersion == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "SdkVersion"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(SdkVersion)); } if (Model == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Model"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(Model)); } if (OemName == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OemName"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(OemName)); } if (OsName == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsName"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(OsName)); } if (OsVersion == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "OsVersion"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(OsVersion)); } if (Locale == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Locale"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(Locale)); } if (ScreenSize == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "ScreenSize"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(ScreenSize)); } if (AppVersion == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppVersion"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(AppVersion)); } if (AppBuild == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "AppBuild"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(AppBuild)); } } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs index b3c160032..8f99a2fed 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/Log.cs @@ -62,14 +62,14 @@ protected Log() { } /// /// Validate the object. /// - /// + /// /// Thrown if validation fails /// public virtual void Validate() { if (Device == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Device"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(Device)); } Device.Validate(); } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs index dd81f648d..f5fc340ed 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/LogContainer.cs @@ -30,18 +30,18 @@ public LogContainer(IList logs) /// /// Validate the object. /// - /// + /// /// Thrown if validation fails /// public virtual void Validate() { if (Logs == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "Logs"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(Logs)); } - if (Logs.Count < 1) + if (Logs.Count == 0) { - throw new Rest.ValidationException(Rest.ValidationRules.MinItems, "Logs", 1); + throw new ValidationException(ValidationException.Rule.CannotBeEmpty, nameof(Logs)); } foreach (var element in Logs) { diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs index e1428e75f..a6a841500 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/StartServiceLog.cs @@ -49,7 +49,7 @@ public StartServiceLog() /// /// Validate the object. /// - /// + /// /// Thrown if validation fails /// public override void Validate() @@ -58,7 +58,7 @@ public override void Validate() if (Services == null) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, nameof(Services)); + throw new ValidationException(ValidationException.Rule.CannotBeNull, nameof(Services)); } } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems index 2cb94724e..ce0956760 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems @@ -22,6 +22,7 @@ + diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Analytics.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Analytics.cs index e30b99a01..459d3168a 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Analytics.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Analytics.cs @@ -2,8 +2,8 @@ using System.Collections.Generic; using Microsoft.Azure.Mobile.Channel; using Microsoft.Azure.Mobile.Analytics.Ingestion.Models; -using Microsoft.Azure.Mobile.Ingestion.Models; using Microsoft.Azure.Mobile.Analytics.Channel; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; using Microsoft.Azure.Mobile.Utils; namespace Microsoft.Azure.Mobile.Analytics diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs index b3dbe420a..5fef0061d 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Push.cs @@ -1,5 +1,5 @@ using Microsoft.Azure.Mobile.Channel; -using Microsoft.Azure.Mobile.Ingestion.Models; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; using Microsoft.Azure.Mobile.Push.Ingestion.Models; using Microsoft.Azure.Mobile.Utils.Synchronization; diff --git a/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj b/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj index ab33dcb1e..d99f9a84e 100644 --- a/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj +++ b/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj @@ -46,9 +46,6 @@ MinimumRecommendedRules.ruleset - - ..\..\packages\Microsoft.Rest.ClientRuntime.2.3.5\lib\net45\Microsoft.Rest.ClientRuntime.dll - ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll diff --git a/Tests/Microsoft.Azure.Mobile.NET/packages.config b/Tests/Microsoft.Azure.Mobile.NET/packages.config index d308cebfe..158f76539 100644 --- a/Tests/Microsoft.Azure.Mobile.NET/packages.config +++ b/Tests/Microsoft.Azure.Mobile.NET/packages.config @@ -1,7 +1,6 @@  - diff --git a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Ingestion/Models/PushInstallationLogTest.cs b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Ingestion/Models/PushInstallationLogTest.cs index d23c79b82..0cd19d35d 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Ingestion/Models/PushInstallationLogTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Ingestion/Models/PushInstallationLogTest.cs @@ -1,5 +1,5 @@ -using Moq; -using Microsoft.Azure.Mobile.Push.Shared.Ingestion.Models; +using Microsoft.Azure.Mobile.Push.Ingestion.Models; +using Moq; using Microsoft.Rest; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs index f654429a1..c8e28ccf3 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs @@ -5,6 +5,7 @@ using Microsoft.Azure.Mobile.Channel; using Microsoft.Azure.Mobile.Storage; using Microsoft.Azure.Mobile.Ingestion.Models; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; using Microsoft.VisualStudio.TestTools.UnitTesting; using Moq; diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/CustomPropertiesLogTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/CustomPropertiesLogTest.cs index d2079c3ab..366aa696d 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/CustomPropertiesLogTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/CustomPropertiesLogTest.cs @@ -3,6 +3,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; namespace Microsoft.Azure.Mobile.Test.Windows.Ingestion.Models { diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/JsonLogConverterTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/JsonLogConverterTest.cs index 78342c358..4b14cdbff 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/JsonLogConverterTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/JsonLogConverterTest.cs @@ -1,4 +1,4 @@ -using Microsoft.Azure.Mobile.Ingestion.Models; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -60,7 +60,7 @@ public void ReadJsonDoesntThrowExceptionForExpectedTypeName() private JObject CreateJObjectWithType(string type) { JObject jObj = new JObject(); - jObj.Add(LogSerializer.TypeIdKey, TestType); + jObj.Add(LogJsonConverter.TypeIdKey, type); return jObj; } } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/LogContainerTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/LogContainerTest.cs index 11c663fbf..030f6c630 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/LogContainerTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/LogContainerTest.cs @@ -1,5 +1,4 @@ using Moq; -using Microsoft.Rest; using Microsoft.Azure.Mobile.Ingestion.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; using System.Collections.Generic; diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/LogTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/LogTest.cs index dedc91f87..b985e6f76 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/LogTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/LogTest.cs @@ -1,5 +1,4 @@ using Moq; -using Microsoft.Rest; using Microsoft.Azure.Mobile.Ingestion.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/StartServiceLogTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/StartServiceLogTest.cs index 4495b5f10..5d31735d0 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/StartServiceLogTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/StartServiceLogTest.cs @@ -3,6 +3,7 @@ using Microsoft.VisualStudio.TestTools.UnitTesting; using System; using System.Collections.Generic; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; namespace Microsoft.Azure.Mobile.Test.Windows.Ingestion.Models { diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/TestLog.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/TestLog.cs index 6ab3c8bd6..4b4e75d71 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/TestLog.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/TestLog.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Microsoft.Azure.Mobile.Ingestion.Models; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; using Newtonsoft.Json; namespace Microsoft.Azure.Mobile.Test From dbdea5f1555094bf338a23785e1843f52de79e4c Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 23 May 2017 10:13:03 -0700 Subject: [PATCH 18/90] Add validation exception and scrub autorest from solution --- .../Microsoft.Azure.Mobile.UWP/project.json | 2 +- .../Ingestion/Models/ValidationException.cs | 65 +++++++++++++++++++ .../project.json | 3 +- .../Ingestion/Models/EventLog.cs | 4 +- .../Ingestion/Models/PageLog.cs | 4 +- .../Ingestion/Models/StartSessionLog.cs | 11 ---- .../project.json | 3 +- .../Ingestion/Models/PushInstallationLog.cs | 4 +- ...icrosoft.Azure.Mobile.Analytics.NET.csproj | 7 +- .../packages.config | 3 +- .../Ingestion/Models/EventLogTest.cs | 2 +- .../Ingestion/Models/PageLogTest.cs | 2 +- ...Azure.Mobile.Analytics.Test.Windows.csproj | 9 +-- .../packages.config | 3 +- .../Microsoft.Azure.Mobile.NET.csproj | 4 +- .../packages.config | 2 +- .../Microsoft.Azure.Mobile.Push.NET.csproj | 8 +-- .../packages.config | 3 +- .../Models/PushInstallationLogTest.cs | 4 +- ...soft.Azure.Mobile.Push.Test.Windows.csproj | 8 +-- .../packages.config | 3 +- .../Models/CustomPropertiesLogTest.cs | 2 +- .../Ingestion/Models/DeviceTest.cs | 2 +- .../Ingestion/Models/JsonLogConverterTest.cs | 33 +++++++++- .../Ingestion/Models/StartServiceLogTest.cs | 2 +- ...Microsoft.Azure.Mobile.Test.Windows.csproj | 7 +- .../packages.config | 3 +- 27 files changed, 131 insertions(+), 72 deletions(-) create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/ValidationException.cs diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/project.json b/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/project.json index 2ffba8f78..cd7bde96b 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/project.json +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/project.json @@ -1,7 +1,7 @@ { "dependencies": { "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", - "Microsoft.Rest.ClientRuntime": "2.3.6", + "Newtonsoft.Json": "6.0.1", "sqlite-net-pcl": "1.3.1" }, "frameworks": { diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/ValidationException.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/ValidationException.cs new file mode 100644 index 000000000..e8bdc075e --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Ingestion/Models/ValidationException.cs @@ -0,0 +1,65 @@ +namespace Microsoft.Azure.Mobile.Ingestion.Models +{ + /// + /// Exception thrown when ingestion models fail to validate + /// + public class ValidationException : IngestionException + { + private const string DefaultMessage = "Validation failed"; + + /// + /// Validation rules that recognizes + /// + public enum Rule + { + CannotBeNull, + CannotBeEmpty + } + + /// + /// Gets a string message that describes a given validation rule + /// + /// The rule to create a string for + /// A string describing the rule + private static string GetRuleString(Rule rule) + { + switch (rule) + { + case Rule.CannotBeNull: + return "Cannot be null"; + case Rule.CannotBeEmpty: + return "Cannot be empty"; + default: + return "Unknown rule"; + } + } + + /// + /// Constructs a full error string to be used as an exception message + /// + /// The rule that was broken + /// The name of the property that broke the rule + /// + private static string GetErrorString(Rule validationRule, string propertyName) + { + return $"Validation failed due to property '{propertyName}': {GetRuleString(validationRule)}"; + } + + public ValidationException() : base(DefaultMessage) + { + } + + public ValidationException(string message) : base(message) + { + } + + /// + /// Creates a validation exception and populates its message + /// + /// The rule that was broken + /// The name of the property that broke the rule + public ValidationException(Rule validationRule, string propertyName) : base(GetErrorString(validationRule, propertyName)) + { + } + } +} diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/project.json b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/project.json index 554c0b8dd..32d927479 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/project.json +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/project.json @@ -1,7 +1,6 @@ { "dependencies": { - "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", - "Microsoft.Rest.ClientRuntime": "2.3.6" + "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2" }, "frameworks": { "uap10.0": {} diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/EventLog.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/EventLog.cs index 2131d644d..d5ed16708 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/EventLog.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/EventLog.cs @@ -62,7 +62,7 @@ public EventLog() { } /// /// Validate the object. /// - /// + /// /// Thrown if validation fails /// public override void Validate() @@ -70,7 +70,7 @@ public override void Validate() base.Validate(); if (Name == null) { - throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.CannotBeNull, "Name"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, "Name"); } } } diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/PageLog.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/PageLog.cs index 239753a9b..7b08a8eaf 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/PageLog.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/PageLog.cs @@ -52,7 +52,7 @@ public PageLog() { } /// /// Validate the object. /// - /// + /// /// Thrown if validation fails /// public override void Validate() @@ -60,7 +60,7 @@ public override void Validate() base.Validate(); if (Name == null) { - throw new Microsoft.Rest.ValidationException(Microsoft.Rest.ValidationRules.CannotBeNull, "Name"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, "Name"); } } } diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/StartSessionLog.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/StartSessionLog.cs index ce80e6644..240b1a0d1 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/StartSessionLog.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Ingestion/Models/StartSessionLog.cs @@ -38,17 +38,6 @@ public StartSessionLog() { } : base(toffset, device, sid) { } - - /// - /// Validate the object. - /// - /// - /// Thrown if validation fails - /// - public override void Validate() - { - base.Validate(); - } } } diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/project.json b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/project.json index 6e581042d..01dadcdfc 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/project.json +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/project.json @@ -1,8 +1,7 @@ { "dependencies": { "Microsoft.NETCore.UniversalWindowsPlatform": "5.2.2", - "Microsoft.Rest.ClientRuntime": "2.3.6", - "Newtonsoft.Json": "9.0.1" + "Newtonsoft.Json": "6.0.1" }, "frameworks": { "uap10.0": {} diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Ingestion/Models/PushInstallationLog.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Ingestion/Models/PushInstallationLog.cs index cd7b9ddc3..a590145bb 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Ingestion/Models/PushInstallationLog.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Windows.Shared/Ingestion/Models/PushInstallationLog.cs @@ -23,7 +23,7 @@ public class PushInstallationLog : Log /// /// Validate the PushInstallationLog /// - /// + /// /// Thrown if PushToken is null or empty /// public override void Validate() @@ -32,7 +32,7 @@ public override void Validate() if (string.IsNullOrEmpty(this.PushToken)) { - throw new Rest.ValidationException(Rest.ValidationRules.CannotBeNull, "PushToken"); + throw new ValidationException(ValidationException.Rule.CannotBeNull, "PushToken"); } } } diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.NET/Microsoft.Azure.Mobile.Analytics.NET.csproj b/Tests/Microsoft.Azure.Mobile.Analytics.NET/Microsoft.Azure.Mobile.Analytics.NET.csproj index 5e736b2f5..43950b612 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.NET/Microsoft.Azure.Mobile.Analytics.NET.csproj +++ b/Tests/Microsoft.Azure.Mobile.Analytics.NET/Microsoft.Azure.Mobile.Analytics.NET.csproj @@ -39,11 +39,8 @@ MinimumRecommendedRules.ruleset - - ..\..\packages\Microsoft.Rest.ClientRuntime.2.3.5\lib\net45\Microsoft.Rest.ClientRuntime.dll - - - ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.6.0.1\lib\net45\Newtonsoft.Json.dll diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.NET/packages.config b/Tests/Microsoft.Azure.Mobile.Analytics.NET/packages.config index c15ed7ad9..aa8e3da7c 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.NET/packages.config +++ b/Tests/Microsoft.Azure.Mobile.Analytics.NET/packages.config @@ -1,5 +1,4 @@  - - + \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Ingestion/Models/EventLogTest.cs b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Ingestion/Models/EventLogTest.cs index 5c17cbeb9..ca51a00c4 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Ingestion/Models/EventLogTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Ingestion/Models/EventLogTest.cs @@ -1,7 +1,7 @@ using Moq; using System; -using Microsoft.Rest; using Microsoft.Azure.Mobile.Analytics.Ingestion.Models; +using Microsoft.Azure.Mobile.Ingestion.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Microsoft.Azure.Mobile.Test.Windows.Ingestion.Models diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Ingestion/Models/PageLogTest.cs b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Ingestion/Models/PageLogTest.cs index 68117d25b..4f491ad2d 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Ingestion/Models/PageLogTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Ingestion/Models/PageLogTest.cs @@ -1,6 +1,6 @@ using Moq; -using Microsoft.Rest; using Microsoft.Azure.Mobile.Analytics.Ingestion.Models; +using Microsoft.Azure.Mobile.Ingestion.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Microsoft.Azure.Mobile.Test.Windows.Ingestion.Models diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Microsoft.Azure.Mobile.Analytics.Test.Windows.csproj b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Microsoft.Azure.Mobile.Analytics.Test.Windows.csproj index bac7ed89a..2a26684d4 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Microsoft.Azure.Mobile.Analytics.Test.Windows.csproj +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Microsoft.Azure.Mobile.Analytics.Test.Windows.csproj @@ -50,10 +50,6 @@ ..\..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll - - ..\..\packages\Microsoft.Rest.ClientRuntime.2.3.5\lib\net45\Microsoft.Rest.ClientRuntime.dll - True - ..\..\packages\MSTest.TestFramework.1.1.11\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll @@ -63,9 +59,8 @@ ..\..\packages\Moq.4.7.1\lib\net45\Moq.dll - - ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll - True + + ..\..\packages\Newtonsoft.Json.6.0.1\lib\net45\Newtonsoft.Json.dll diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/packages.config b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/packages.config index 362f20d9d..0c0a2516b 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/packages.config +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/packages.config @@ -1,9 +1,8 @@  - - + \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj b/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj index d99f9a84e..6d8d63414 100644 --- a/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj +++ b/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj @@ -46,8 +46,8 @@ MinimumRecommendedRules.ruleset - - ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.6.0.1\lib\net45\Newtonsoft.Json.dll ..\..\packages\sqlite-net-pcl.1.3.1\lib\netstandard1.1\SQLite-net.dll diff --git a/Tests/Microsoft.Azure.Mobile.NET/packages.config b/Tests/Microsoft.Azure.Mobile.NET/packages.config index 158f76539..3956c2afd 100644 --- a/Tests/Microsoft.Azure.Mobile.NET/packages.config +++ b/Tests/Microsoft.Azure.Mobile.NET/packages.config @@ -2,7 +2,7 @@ - + diff --git a/Tests/Microsoft.Azure.Mobile.Push.NET/Microsoft.Azure.Mobile.Push.NET.csproj b/Tests/Microsoft.Azure.Mobile.Push.NET/Microsoft.Azure.Mobile.Push.NET.csproj index baeb6c673..fbfa9b0a8 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.NET/Microsoft.Azure.Mobile.Push.NET.csproj +++ b/Tests/Microsoft.Azure.Mobile.Push.NET/Microsoft.Azure.Mobile.Push.NET.csproj @@ -30,12 +30,8 @@ 4 - - ..\..\packages\Microsoft.Rest.ClientRuntime.2.3.6\lib\net45\Microsoft.Rest.ClientRuntime.dll - - - ..\..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll - True + + ..\..\packages\Newtonsoft.Json.6.0.1\lib\net45\Newtonsoft.Json.dll diff --git a/Tests/Microsoft.Azure.Mobile.Push.NET/packages.config b/Tests/Microsoft.Azure.Mobile.Push.NET/packages.config index e0936f484..aa8e3da7c 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.NET/packages.config +++ b/Tests/Microsoft.Azure.Mobile.Push.NET/packages.config @@ -1,5 +1,4 @@  - - + \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Ingestion/Models/PushInstallationLogTest.cs b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Ingestion/Models/PushInstallationLogTest.cs index 0cd19d35d..a5c2ab986 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Ingestion/Models/PushInstallationLogTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Ingestion/Models/PushInstallationLogTest.cs @@ -1,6 +1,6 @@ -using Microsoft.Azure.Mobile.Push.Ingestion.Models; +using Microsoft.Azure.Mobile.Ingestion.Models; +using Microsoft.Azure.Mobile.Push.Ingestion.Models; using Moq; -using Microsoft.Rest; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Microsoft.Azure.Mobile.Test.Windows.Ingestion.Models diff --git a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj index b74072fd7..c18f8929a 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj +++ b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj @@ -42,9 +42,6 @@ ..\..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll True - - ..\..\packages\Microsoft.Rest.ClientRuntime.2.3.6\lib\net45\Microsoft.Rest.ClientRuntime.dll - ..\..\packages\MSTest.TestFramework.1.1.11\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll @@ -55,9 +52,8 @@ ..\..\packages\Moq.4.7.8\lib\net45\Moq.dll True - - ..\..\packages\Newtonsoft.Json.10.0.2\lib\net45\Newtonsoft.Json.dll - True + + ..\..\packages\Newtonsoft.Json.6.0.1\lib\net45\Newtonsoft.Json.dll diff --git a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/packages.config b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/packages.config index 3674e054c..5cfe0ed90 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/packages.config +++ b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/packages.config @@ -1,9 +1,8 @@  - - + \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/CustomPropertiesLogTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/CustomPropertiesLogTest.cs index 366aa696d..0c5322a91 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/CustomPropertiesLogTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/CustomPropertiesLogTest.cs @@ -81,7 +81,7 @@ public void ValidateStartServiceLog() Toffset = TimeHelper.CurrentTimeInMilliseconds() }; - Assert.ThrowsException((Action)log.Validate); + Assert.ThrowsException((Action)log.Validate); } } } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/DeviceTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/DeviceTest.cs index 2ca712a53..a1735099f 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/DeviceTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/DeviceTest.cs @@ -1,4 +1,4 @@ -using Microsoft.Rest; +using Microsoft.Azure.Mobile.Ingestion.Models; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace Microsoft.Azure.Mobile.Test.Ingestion.Models diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/JsonLogConverterTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/JsonLogConverterTest.cs index 4b14cdbff..f4d4d59f1 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/JsonLogConverterTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/JsonLogConverterTest.cs @@ -1,4 +1,5 @@ -using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; +using System; +using Microsoft.Azure.Mobile.Ingestion.Models.Serialization; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json; using Newtonsoft.Json.Linq; @@ -11,6 +12,36 @@ public override bool Read() { return true; } + + public override int? ReadAsInt32() + { + throw new NotImplementedException(); + } + + public override string ReadAsString() + { + throw new NotImplementedException(); + } + + public override byte[] ReadAsBytes() + { + throw new NotImplementedException(); + } + + public override decimal? ReadAsDecimal() + { + throw new NotImplementedException(); + } + + public override DateTime? ReadAsDateTime() + { + throw new NotImplementedException(); + } + + public override DateTimeOffset? ReadAsDateTimeOffset() + { + throw new NotImplementedException(); + } } [TestClass] diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/StartServiceLogTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/StartServiceLogTest.cs index 5d31735d0..23df8738e 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/StartServiceLogTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Ingestion/Models/StartServiceLogTest.cs @@ -87,7 +87,7 @@ public void ValidateStartServiceLog() Toffset = TimeHelper.CurrentTimeInMilliseconds() }; - Assert.ThrowsException((Action)log.Validate); + Assert.ThrowsException((Action)log.Validate); } } } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Microsoft.Azure.Mobile.Test.Windows.csproj b/Tests/Microsoft.Azure.Mobile.Test.Windows/Microsoft.Azure.Mobile.Test.Windows.csproj index 1a824afe4..48b7ca032 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Microsoft.Azure.Mobile.Test.Windows.csproj +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Microsoft.Azure.Mobile.Test.Windows.csproj @@ -50,9 +50,6 @@ ..\..\packages\Castle.Core.4.0.0\lib\net45\Castle.Core.dll - - ..\..\packages\Microsoft.Rest.ClientRuntime.2.3.5\lib\net45\Microsoft.Rest.ClientRuntime.dll - ..\..\packages\MSTest.TestFramework.1.1.11\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll @@ -62,8 +59,8 @@ ..\..\packages\Moq.4.7.1\lib\net45\Moq.dll - - ..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll + + ..\..\packages\Newtonsoft.Json.6.0.1\lib\net45\Newtonsoft.Json.dll ..\..\packages\sqlite-net-pcl.1.3.1\lib\netstandard1.1\SQLite-net.dll diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/packages.config b/Tests/Microsoft.Azure.Mobile.Test.Windows/packages.config index 09db0f451..1b25726b8 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/packages.config +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/packages.config @@ -2,12 +2,11 @@ - - + From b39ad97a436b847c19493d061e03d60b294792e8 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 23 May 2017 10:38:32 -0700 Subject: [PATCH 19/90] Remove app.config files from tests as they are not updated correctly and not needed --- .../Microsoft.Azure.Mobile.Analytics.NET.csproj | 1 - .../app.config | 11 ----------- ...soft.Azure.Mobile.Analytics.Test.Windows.csproj | 1 - .../app.config | 11 ----------- Tests/Microsoft.Azure.Mobile.NET/App.config | 14 -------------- .../Microsoft.Azure.Mobile.NET.csproj | 1 - .../Microsoft.Azure.Mobile.Push.NET.csproj | 1 - Tests/Microsoft.Azure.Mobile.Push.NET/app.config | 11 ----------- ...Microsoft.Azure.Mobile.Push.Test.Windows.csproj | 1 - .../app.config | 11 ----------- .../Microsoft.Azure.Mobile.Test.Windows.csproj | 1 - .../Microsoft.Azure.Mobile.Test.Windows/app.config | 11 ----------- 12 files changed, 75 deletions(-) delete mode 100644 Tests/Microsoft.Azure.Mobile.Analytics.NET/app.config delete mode 100644 Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/app.config delete mode 100644 Tests/Microsoft.Azure.Mobile.NET/App.config delete mode 100644 Tests/Microsoft.Azure.Mobile.Push.NET/app.config delete mode 100644 Tests/Microsoft.Azure.Mobile.Push.Test.Windows/app.config delete mode 100644 Tests/Microsoft.Azure.Mobile.Test.Windows/app.config diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.NET/Microsoft.Azure.Mobile.Analytics.NET.csproj b/Tests/Microsoft.Azure.Mobile.Analytics.NET/Microsoft.Azure.Mobile.Analytics.NET.csproj index 43950b612..36c558d78 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.NET/Microsoft.Azure.Mobile.Analytics.NET.csproj +++ b/Tests/Microsoft.Azure.Mobile.Analytics.NET/Microsoft.Azure.Mobile.Analytics.NET.csproj @@ -58,7 +58,6 @@ - diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.NET/app.config b/Tests/Microsoft.Azure.Mobile.Analytics.NET/app.config deleted file mode 100644 index 8460dd432..000000000 --- a/Tests/Microsoft.Azure.Mobile.Analytics.NET/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Microsoft.Azure.Mobile.Analytics.Test.Windows.csproj b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Microsoft.Azure.Mobile.Analytics.Test.Windows.csproj index 2a26684d4..bcc223ed6 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Microsoft.Azure.Mobile.Analytics.Test.Windows.csproj +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Microsoft.Azure.Mobile.Analytics.Test.Windows.csproj @@ -80,7 +80,6 @@ - diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/app.config b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/app.config deleted file mode 100644 index 8460dd432..000000000 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.NET/App.config b/Tests/Microsoft.Azure.Mobile.NET/App.config deleted file mode 100644 index 71a06ba30..000000000 --- a/Tests/Microsoft.Azure.Mobile.NET/App.config +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj b/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj index 6d8d63414..0198cb596 100644 --- a/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj +++ b/Tests/Microsoft.Azure.Mobile.NET/Microsoft.Azure.Mobile.NET.csproj @@ -93,7 +93,6 @@ - diff --git a/Tests/Microsoft.Azure.Mobile.Push.NET/Microsoft.Azure.Mobile.Push.NET.csproj b/Tests/Microsoft.Azure.Mobile.Push.NET/Microsoft.Azure.Mobile.Push.NET.csproj index fbfa9b0a8..b62397f8b 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.NET/Microsoft.Azure.Mobile.Push.NET.csproj +++ b/Tests/Microsoft.Azure.Mobile.Push.NET/Microsoft.Azure.Mobile.Push.NET.csproj @@ -56,7 +56,6 @@ - diff --git a/Tests/Microsoft.Azure.Mobile.Push.NET/app.config b/Tests/Microsoft.Azure.Mobile.Push.NET/app.config deleted file mode 100644 index dde2c3cc6..000000000 --- a/Tests/Microsoft.Azure.Mobile.Push.NET/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj index c18f8929a..542029527 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj +++ b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Microsoft.Azure.Mobile.Push.Test.Windows.csproj @@ -86,7 +86,6 @@ - diff --git a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/app.config b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/app.config deleted file mode 100644 index dde2c3cc6..000000000 --- a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Microsoft.Azure.Mobile.Test.Windows.csproj b/Tests/Microsoft.Azure.Mobile.Test.Windows/Microsoft.Azure.Mobile.Test.Windows.csproj index 48b7ca032..f3cba1be4 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Microsoft.Azure.Mobile.Test.Windows.csproj +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Microsoft.Azure.Mobile.Test.Windows.csproj @@ -131,7 +131,6 @@ - Designer diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/app.config b/Tests/Microsoft.Azure.Mobile.Test.Windows/app.config deleted file mode 100644 index 8460dd432..000000000 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file From 845cff348975ba84abd407c6b4291ead217e72e2 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Tue, 23 May 2017 10:40:49 -0700 Subject: [PATCH 20/90] Change nuget dependencies from autorest to newtonsoft.json --- nuget/MobileCenter.nuspec | 2 +- nuget/WindowsMobileCenter.nuspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/nuget/MobileCenter.nuspec b/nuget/MobileCenter.nuspec index 040f22428..6f36fbe75 100644 --- a/nuget/MobileCenter.nuspec +++ b/nuget/MobileCenter.nuspec @@ -14,7 +14,7 @@ - + diff --git a/nuget/WindowsMobileCenter.nuspec b/nuget/WindowsMobileCenter.nuspec index 148156728..09eb16bfc 100644 --- a/nuget/WindowsMobileCenter.nuspec +++ b/nuget/WindowsMobileCenter.nuspec @@ -14,7 +14,7 @@ - + From 730830004546ad35b7adefb84fab948ca65934f1 Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 25 May 2017 01:06:08 +0300 Subject: [PATCH 21/90] Fix remarks --- .../Channel/Channel.cs | 100 +++++++------ .../MobileCenter.cs | 1 - .../Storage/Storage.cs | 4 +- .../Utils/Synchronization/StatefulMutex.cs | 137 +++++++----------- .../MobileCenterTest.cs | 12 -- 5 files changed, 105 insertions(+), 149 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs index 82db49247..f21aedada 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs @@ -41,27 +41,12 @@ internal Channel(string name, int maxLogsPerBatch, TimeSpan batchTimeInterval, i _batchScheduled = false; _enabled = true; DeviceInformationHelper.InformationInvalidated += (sender, e) => InvalidateDeviceCache(); - } - - public async Task SetEnabledAsync(bool enabled) - { - State state; - using (await _mutex.GetLockAsync().ConfigureAwait(false)) - { - if (_enabled == enabled) - { - return; - } - state = _mutex.State; - } - if (enabled) - { - await ResumeAsync(state).ConfigureAwait(false); - } - else + var lockHolder = _mutex.GetLock(); + Task.Run(() => _storage.CountLogsAsync(Name)).ContinueWith(task => { - await SuspendAsync(state, true, new CancellationException()).ConfigureAwait(false); - } + _pendingLogCount = task.Result; + lockHolder.Dispose(); + }); } /// @@ -90,6 +75,27 @@ public bool IsEnabled public event EventHandler FailedToSendLog; #endregion + public async Task SetEnabledAsync(bool enabled) + { + State state; + using (await _mutex.GetLockAsync().ConfigureAwait(false)) + { + if (_enabled == enabled) + { + return; + } + state = _mutex.State; + } + if (enabled) + { + await ResumeAsync(state).ConfigureAwait(false); + } + else + { + await SuspendAsync(state, true, new CancellationException()).ConfigureAwait(false); + } + } + public async Task EnqueueAsync(Log log) { try @@ -173,7 +179,7 @@ public void InvalidateDeviceCache() _device = null; } } - + public async Task ClearAsync() { var state = _mutex.State; @@ -199,13 +205,7 @@ private async Task ResumeAsync(State state) { _enabled = true; _discardLogs = false; - _mutex.InvalidateState(); - state = _mutex.State; - } - var logCount = await _storage.CountLogsAsync(Name).ConfigureAwait(false); - using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) - { - _pendingLogCount = logCount; + state = _mutex.InvalidateState(); } } catch (StatefulMutexException e) @@ -226,27 +226,35 @@ private async Task SuspendAsync(State state, bool deleteLogs, Exception exceptio _discardLogs = deleteLogs; _mutex.InvalidateState(); } - } - catch (StatefulMutexException e) - { - MobileCenterLog.Warn(MobileCenterLog.LogTag, "The Suspend operation has been cancelled", e); - } - if (deleteLogs && FailedToSendLog != null) - { - foreach (var log in _sendingBatches.Values.SelectMany(batch => batch)) + if (deleteLogs && FailedToSendLog != null) { - FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, exception)); + foreach (var log in _sendingBatches.Values.SelectMany(batch => batch)) + { + FailedToSendLog?.Invoke(this, new FailedToSendLogEventArgs(log, exception)); + } } + try + { + _ingestion.Close(); + } + catch (IngestionException e) + { + MobileCenterLog.Error(MobileCenterLog.LogTag, "Failed to close ingestion", e); + } + if (deleteLogs) + { + using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) + { + _pendingLogCount = 0; + } + await DeleteLogsOnSuspendedAsync().ConfigureAwait(false); + } + await _storage.ClearPendingLogStateAsync(Name).ConfigureAwait(false); } - try - { - _ingestion.Close(); - } - catch (IngestionException e) + catch (StatefulMutexException e) { - MobileCenterLog.Error(MobileCenterLog.LogTag, "Failed to close ingestion", e); + MobileCenterLog.Warn(MobileCenterLog.LogTag, "The Suspend operation has been cancelled", e); } - await _storage.ClearPendingLogStateAsync(Name).ConfigureAwait(false); } private async Task DeleteLogsOnSuspendedAsync() @@ -408,8 +416,7 @@ private async Task CheckPendingLogsAsync(State state) _batchScheduled = true; // No need wait _batchTimeInterval here. -#pragma warning disable CS4014 - Task.Run(async () => + var _ = Task.Run(async () => { await Task.Delay((int)_batchTimeInterval.TotalMilliseconds).ConfigureAwait(false); if (_batchScheduled) @@ -417,7 +424,6 @@ private async Task CheckPendingLogsAsync(State state) await TriggerIngestionAsync(_mutex.State).ConfigureAwait(false); } }); -#pragma warning restore CS4014 } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs index 880aa5d08..3a8ac7bc9 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/MobileCenter.cs @@ -288,7 +288,6 @@ internal void InstanceConfigure(string appSecretOrSecrets) _applicationLifecycleHelper.UnhandledExceptionOccurred += (sender, e) => _channelGroup.ShutdownAsync(); _channel = _channelGroup.AddChannel(ChannelName, Constants.DefaultTriggerCount, Constants.DefaultTriggerInterval, Constants.DefaultTriggerMaxParallelRequests); - _channel.SetEnabledAsync(true); if (_logUrl != null) { _channelGroup.SetLogUrl(_logUrl); diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs index f446d5e07..e0410903e 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs @@ -47,8 +47,8 @@ public Storage() : this(new StorageAdapter(Database)) internal Storage(IStorageAdapter adapter) { _storageAdapter = adapter; - _mutex.Lock(); - Task.Run(InitializeDatabaseAsync).ContinueWith(completedTask => _mutex.Unlock()); + var lockHolder = _mutex.GetLock(); + Task.Run(InitializeDatabaseAsync).ContinueWith(completedTask => lockHolder.Dispose()); } /// diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs index fb2f188be..f71177928 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Utils/Synchronization/StatefulMutex.cs @@ -11,12 +11,10 @@ namespace Microsoft.Azure.Mobile.Utils.Synchronization /// public class StatefulMutex : IDisposable { - private const string ShutdownExceptionMessage = "Trying to execute task after shutdown requested"; - private const string StateExceptionMessage = "Cannot lock mutex with expired state"; - private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1, 1); private State _state = new State(); private volatile bool _isShutdown; + private volatile int _waitingThreads; /// /// Gets the current state @@ -30,128 +28,93 @@ public State State /// /// Advances the current state /// - public void InvalidateState() + /// The new state + public State InvalidateState() { _state = _state.GetNextState(); + return _state; } - /// - /// Checks if the given state is current - /// - /// The state to test - /// True if the current state is current, false otherwise - public bool IsCurrent(State state) - { - return _state.Equals(state); - } - - public async Task ShutdownAsync() - { - await _mutex.WaitAsync().ConfigureAwait(false); - _isShutdown = true; - _mutex.Release(); - } - - public async Task ShutdownAsync(TimeSpan timeout) - { - var result = await _mutex.WaitAsync(timeout).ConfigureAwait(false); - _isShutdown = true; - _mutex.Release(); - return result; - } - - /// - /// Locks the mutex and does not verify any state - /// - /// - public void Lock() + private void StartWait() { - _mutex.Wait(); + Interlocked.Increment(ref _waitingThreads); + Interlocked.MemoryBarrier(); if (_isShutdown) { - throw new StatefulMutexException(ShutdownExceptionMessage); + Interlocked.Decrement(ref _waitingThreads); + throw new StatefulMutexException("Trying to execute task after shutdown requested"); } } - /// - /// Locks the mutex if the given is consistent with the mutex's state - /// - /// The that must be consistent with the mutex's state - /// The given state is invalid - /// - public void Lock(State stateSnapshot) + private void StopWait() { - _mutex.Wait(); - if (_isShutdown) - { - throw new StatefulMutexException(ShutdownExceptionMessage); - } - if (!IsCurrent(stateSnapshot)) - { - throw new StatefulMutexException(StateExceptionMessage); - } + Interlocked.Decrement(ref _waitingThreads); } /// - /// Asynchronously locks the mutex and does not verify any state + /// Checks if the given state is current /// - /// - public async Task LockAsync() + /// The state to test + /// True if the current state is current, false otherwise + public bool IsCurrent(State state) { - await _mutex.WaitAsync().ConfigureAwait(false); - if (_isShutdown) - { - throw new StatefulMutexException(ShutdownExceptionMessage); - } + return _state.Equals(state); } - /// - /// Locks the mutex if the given is consistent with the mutex's state - /// - /// The that must be consistent with the mutex's state - /// The given state is invalid - /// - public async Task LockAsync(State stateSnapshot) + public async Task ShutdownAsync() { - await _mutex.WaitAsync().ConfigureAwait(false); - if (_isShutdown) - { - throw new StatefulMutexException(ShutdownExceptionMessage); - } - if (!IsCurrent(stateSnapshot)) + _isShutdown = true; + Interlocked.MemoryBarrier(); + while (_waitingThreads > 0) { - Unlock(); - throw new StatefulMutexException(StateExceptionMessage); + await _mutex.WaitAsync().ConfigureAwait(false); + _mutex.Release(); } } - /// - /// Unlocks the mutex. Consecutive calls will not throw an exception - /// - public void Unlock() + public async Task ShutdownAsync(TimeSpan timeout) { - if (_mutex.CurrentCount != 0) + var result = true; + var tokenSource = new CancellationTokenSource(); + var timeoutTask = Task.Delay(timeout, tokenSource.Token); + _isShutdown = true; + Interlocked.MemoryBarrier(); + while (result && _waitingThreads > 0) { - throw new StatefulMutexException("Trying to unlock not locked mutex"); + var waitTask = _mutex.WaitAsync(tokenSource.Token); + var _ = waitTask.ContinueWith(task => _mutex.Release(), TaskContinuationOptions.OnlyOnRanToCompletion); + result = await Task.WhenAny(waitTask, timeoutTask).ConfigureAwait(false) != timeoutTask; } - _mutex.Release(); + tokenSource.Cancel(); + return result; } - + public LockHolder GetLock() { - Lock(); + StartWait(); + _mutex.Wait(); + StopWait(); return new LockHolder(this); } public async Task GetLockAsync() { - await LockAsync().ConfigureAwait(false); + StartWait(); + await _mutex.WaitAsync().ConfigureAwait(false); + StopWait(); return new LockHolder(this); } public async Task GetLockAsync(State state) { - await LockAsync(state).ConfigureAwait(false); + StartWait(); + await _mutex.WaitAsync().ConfigureAwait(false); + StopWait(); + if (!IsCurrent(state)) + { + _mutex.Release(); + throw new StatefulMutexException("Cannot lock mutex with expired state"); + } return new LockHolder(this); } @@ -174,7 +137,7 @@ internal LockHolder(StatefulMutex parent) public void Dispose() { - _parent.Unlock(); + _parent._mutex.Release(); } } } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs index 0a640cf23..2ac110548 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/MobileCenterTest.cs @@ -337,10 +337,6 @@ public void ConfigureMobileCenterMultipleTimes() public void LogUrlIsNotSetByDefault() { var channelGroupMock = new Mock(); - var channelUnitMock = new Mock(); - channelGroupMock.Setup( - group => group.AddChannel(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(channelUnitMock.Object); MobileCenter.Instance = new MobileCenter(new ApplicationSettings(), new MockChannelGroupFactory(channelGroupMock)); MobileCenter.Configure("appsecret"); @@ -354,10 +350,6 @@ public void LogUrlIsNotSetByDefault() public void SetLogUrlBeforeConfigure() { var channelGroupMock = new Mock(); - var channelUnitMock = new Mock(); - channelGroupMock.Setup( - group => group.AddChannel(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(channelUnitMock.Object); MobileCenter.Instance = new MobileCenter(new ApplicationSettings(), new MockChannelGroupFactory(channelGroupMock)); var customLogUrl = "www dot log url dot com"; @@ -374,10 +366,6 @@ public void SetLogUrlBeforeConfigure() public void SetLogUrlAfterConfigure() { var channelGroupMock = new Mock(); - var channelUnitMock = new Mock(); - channelGroupMock.Setup( - group => group.AddChannel(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(channelUnitMock.Object); MobileCenter.Instance = new MobileCenter(new ApplicationSettings(), new MockChannelGroupFactory(channelGroupMock)); MobileCenter.Configure("appsecret"); From 20c0d712a316a369fe2158a5e0e65677fc5cd68d Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Thu, 25 May 2017 01:37:52 +0300 Subject: [PATCH 22/90] Fix infinity sending logs on exception while delete --- .../Channel/Channel.cs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs index f21aedada..841e3e6ac 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Channel/Channel.cs @@ -318,8 +318,14 @@ private async Task TriggerIngestionAsync(State state) _sendingBatches.Add(batchId, logs); _pendingLogCount -= logs.Count; } - await TriggerIngestionAsync(state, logs, batchId).ConfigureAwait(false); - await CheckPendingLogsAsync(state).ConfigureAwait(false); + try + { + await TriggerIngestionAsync(state, logs, batchId).ConfigureAwait(false); + await CheckPendingLogsAsync(state).ConfigureAwait(false); + } + catch (StorageException) + { + } } } @@ -352,6 +358,7 @@ private async Task TriggerIngestionAsync(State state, IList logs, string ba { return; } + StorageException deleteException = null; try { await _storage.DeleteLogsAsync(Name, batchId).ConfigureAwait(false); @@ -359,6 +366,7 @@ private async Task TriggerIngestionAsync(State state, IList logs, string ba catch (StorageException e) { MobileCenterLog.Warn(MobileCenterLog.LogTag, $"Could not delete logs for batch {batchId}", e); + deleteException = e; } List removedLogs; using (await _mutex.GetLockAsync(state).ConfigureAwait(false)) @@ -373,6 +381,10 @@ private async Task TriggerIngestionAsync(State state, IList logs, string ba SentLog?.Invoke(this, new SentLogEventArgs(log)); } } + if (deleteException != null) + { + throw deleteException; + } } private async Task HandleSendingFailureAsync(State state, string batchId, IngestionException e) From fb81d675c830435d2ac01a6bd0db070e4907e23c Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 25 May 2017 16:51:48 -0700 Subject: [PATCH 23/90] Modify storage to use a task queue --- .../Storage/Storage.cs | 149 ++++++++++++++---- .../Channel/ChannelTest.cs | 3 +- .../Storage/FakeStorageTest.cs | 32 ++-- 3 files changed, 136 insertions(+), 48 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs index 48f09d950..f0fb48225 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Threading.Tasks; using Newtonsoft.Json; @@ -31,7 +32,7 @@ internal class LogEntry private readonly Dictionary> _pendingDbIdentifierGroups = new Dictionary>(); private readonly HashSet _pendingDbIdentifiers = new HashSet(); - private readonly TaskLock.TaskLockSource _taskLockSource = new TaskLock.TaskLockSource(); + private readonly BlockingCollection _queue = new BlockingCollection(); /// /// Creates an instance of Storage @@ -46,8 +47,7 @@ public Storage() : this(new StorageAdapter(Database)) internal Storage(IStorageAdapter adapter) { _storageAdapter = adapter; - var taskLock = _taskLockSource.GetTaskLock(); - Task.Run(InitializeDatabaseAsync).ContinueWith(completedTask => taskLock.Dispose()); + _queue.Add(new Task(async () => await InitializeDatabaseAsync())); } /// @@ -58,12 +58,22 @@ internal Storage(IStorageAdapter adapter) /// public async Task PutLogAsync(string channelName, Log log) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + var task = new Task(() => { var logJsonString = LogSerializer.Serialize(log); - var logEntry = new LogEntry { Channel = channelName, Log = logJsonString }; - await _storageAdapter.InsertAsync(logEntry).ConfigureAwait(false); - } + var logEntry = new LogEntry {Channel = channelName, Log = logJsonString}; + _storageAdapter.InsertAsync(logEntry).Wait(); + }); + try + { + _queue.Add(task); + } + catch (InvalidOperationException) + { + throw new StorageException("The operation has been cancelled"); + } + await FlushQueue().ConfigureAwait(false); + await task.ConfigureAwait(false); } /// @@ -74,12 +84,13 @@ public async Task PutLogAsync(string channelName, Log log) /// public async Task DeleteLogsAsync(string channelName, string batchId) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + var task = new Task(() => { - MobileCenterLog.Debug(MobileCenterLog.LogTag, - $"Deleting logs from storage for channel '{channelName}' with batch id '{batchId}'"); try { + MobileCenterLog.Debug(MobileCenterLog.LogTag, + $"Deleting logs from storage for channel '{channelName}' with batch id '{batchId}'"); + var identifiers = _pendingDbIdentifierGroups[GetFullIdentifier(channelName, batchId)]; _pendingDbIdentifierGroups.Remove(GetFullIdentifier(channelName, batchId)); var deletedIdsMessage = "The IDs for deleting log(s) is/ are:"; @@ -91,14 +102,26 @@ public async Task DeleteLogsAsync(string channelName, string batchId) MobileCenterLog.Debug(MobileCenterLog.LogTag, deletedIdsMessage); foreach (var id in identifiers) { - await _storageAdapter.DeleteAsync(entry => entry.Channel == channelName && entry.Id == id).ConfigureAwait(false); + _storageAdapter + .DeleteAsync(entry => entry.Channel == channelName && entry.Id == id) + .Wait(); } } catch (KeyNotFoundException e) { throw new StorageException(e); } + }); + try + { + _queue.Add(task); + } + catch (InvalidOperationException) + { + throw new StorageException("The operation has been cancelled"); } + await FlushQueue().ConfigureAwait(false); + await task.ConfigureAwait(false); } /// @@ -108,13 +131,14 @@ public async Task DeleteLogsAsync(string channelName, string batchId) /// public async Task DeleteLogsAsync(string channelName) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + var task = new Task(() => { - MobileCenterLog.Debug(MobileCenterLog.LogTag, - $"Deleting all logs from storage for channel '{channelName}'"); - var fullIdentifiers = new List(); try { + MobileCenterLog.Debug(MobileCenterLog.LogTag, + $"Deleting all logs from storage for channel '{channelName}'"); + var fullIdentifiers = new List(); + foreach (var fullIdentifier in _pendingDbIdentifierGroups.Keys) { if (!ChannelMatchesIdentifier(channelName, fullIdentifier)) @@ -131,14 +155,25 @@ public async Task DeleteLogsAsync(string channelName) { _pendingDbIdentifierGroups.Remove(fullIdentifier); } + + _storageAdapter.DeleteAsync(entry => entry.Channel == channelName) + .Wait(); } catch (KeyNotFoundException e) { throw new StorageException(e); } - await _storageAdapter.DeleteAsync(entry => entry.Channel == channelName) - .ConfigureAwait(false); + }); + try + { + _queue.Add(task); } + catch (InvalidOperationException) + { + throw new StorageException("The operation has been cancelled"); + } + await FlushQueue().ConfigureAwait(false); + await task.ConfigureAwait(false); } /// @@ -149,10 +184,27 @@ await _storageAdapter.DeleteAsync(entry => entry.Channel == channelNam /// public async Task CountLogsAsync(string channelName) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + var task = new Task(() => + { + return _storageAdapter.CountAsync(entry => entry.Channel == channelName) + .Result; + }); + try + { + _queue.Add(task); + } + catch (InvalidOperationException) { - return await _storageAdapter.CountAsync(entry => entry.Channel == channelName) - .ConfigureAwait(false); + throw new StorageException("The operation has been cancelled"); + } + try + { + await FlushQueue().ConfigureAwait(false); + return await task.ConfigureAwait(false); + } + catch (AggregateException e) + { + throw e.InnerException ?? new StorageException(); } } @@ -162,11 +214,21 @@ public async Task CountLogsAsync(string channelName) /// public async Task ClearPendingLogStateAsync(string channelName) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + var task = new Task(() => { _pendingDbIdentifierGroups.Clear(); _pendingDbIdentifiers.Clear(); + }); + try + { + _queue.Add(task); + } + catch (InvalidOperationException) + { + throw new StorageException("The operation has been cancelled"); } + await FlushQueue().ConfigureAwait(false); + await task.ConfigureAwait(false); } /// @@ -179,17 +241,19 @@ public async Task ClearPendingLogStateAsync(string channelName) /// public async Task GetLogsAsync(string channelName, int limit, List logs) { - using (await _taskLockSource.GetTaskLockAsync().ConfigureAwait(false)) + + var task = new Task(() => { logs?.Clear(); var retrievedLogs = new List(); - MobileCenterLog.Debug(MobileCenterLog.LogTag, $"Trying to get up to {limit} logs from storage for {channelName}"); + MobileCenterLog.Debug(MobileCenterLog.LogTag, + $"Trying to get up to {limit} logs from storage for {channelName}"); var idPairs = new List>(); var failedToDeserializeALog = false; var retrievedEntries = - await _storageAdapter.GetAsync(entry => entry.Channel == channelName, limit) - .ConfigureAwait(false); + _storageAdapter.GetAsync(entry => entry.Channel == channelName, limit) + .Result; foreach (var entry in retrievedEntries) { if (_pendingDbIdentifiers.Contains(entry.Id)) @@ -206,7 +270,8 @@ await _storageAdapter.GetAsync(entry => entry.Channel == channelName, { MobileCenterLog.Error(MobileCenterLog.LogTag, "Cannot deserialize a log in storage", e); failedToDeserializeALog = true; - await _storageAdapter.DeleteAsync(row => row.Id == entry.Id).ConfigureAwait(false); + _storageAdapter.DeleteAsync(row => row.Id == entry.Id) + .Wait(); } } if (failedToDeserializeALog) @@ -215,7 +280,8 @@ await _storageAdapter.GetAsync(entry => entry.Channel == channelName, } if (idPairs.Count == 0) { - MobileCenterLog.Debug(MobileCenterLog.LogTag, $"No available logs in storage for channel '{channelName}'"); + MobileCenterLog.Debug(MobileCenterLog.LogTag, + $"No available logs in storage for channel '{channelName}'"); return null; } @@ -224,7 +290,19 @@ await _storageAdapter.GetAsync(entry => entry.Channel == channelName, ProcessLogIds(channelName, batchId, idPairs); logs?.AddRange(retrievedLogs); return batchId; + }); + + try + { + _queue.Add(task); } + catch (InvalidOperationException) + { + throw new StorageException("The operation has been cancelled"); + } + + await FlushQueue().ConfigureAwait(false); + return await task.ConfigureAwait(false); } private void ProcessLogIds(string channelName, string batchId, IEnumerable> idPairs) @@ -244,7 +322,6 @@ private void ProcessLogIds(string channelName, string batchId, IEnumerable().ConfigureAwait(false); @@ -263,7 +340,8 @@ private async Task InitializeDatabaseAsync() /// This method blocks the calling thread public bool Shutdown(TimeSpan timeout) { - return _taskLockSource.Shutdown(timeout); + _queue.CompleteAdding(); + return FlushQueue().Wait(timeout); } private static string GetFullIdentifier(string channelName, string identifier) @@ -277,12 +355,23 @@ private static bool ChannelMatchesIdentifier(string channelName, string identifi return identifier.Substring(0, lastDelimiterIndex) == channelName; } + // Flushes the queue + private async Task FlushQueue() + { + while (_queue.Count > 0) + { + var t = _queue.Take(); + t.Start(); + await t.ConfigureAwait(false); + } + } + /// /// Disposes the storage object /// public void Dispose() { - _taskLockSource.Dispose(); + _queue.CompleteAdding(); } } } diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs index c8e28ccf3..3bdd1cc49 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Channel/ChannelTest.cs @@ -16,7 +16,7 @@ public class ChannelTest { private Mobile.Channel.Channel _channel; private readonly MockIngestion _mockIngestion = new MockIngestion(); - private readonly IStorage _storage = new Mobile.Storage.Storage(); + private IStorage _storage = new Mobile.Storage.Storage(); private const string ChannelName = "channelName"; private const int MaxLogsPerBatch = 3; @@ -252,6 +252,7 @@ public void ThrowStorageExceptionInDeleteLogsTime() private void SetChannelWithTimeSpan(TimeSpan timeSpan) { + _storage = new Mobile.Storage.Storage(); _storage.DeleteLogsAsync(ChannelName).Wait(); _channel = new Mobile.Channel.Channel(ChannelName, MaxLogsPerBatch, timeSpan, MaxParallelBatches, _appSecret, _mockIngestion, _storage); diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs index 52ca225bf..108a01b2f 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Storage/FakeStorageTest.cs @@ -27,24 +27,17 @@ public void ShutdownTimeout() var mockConnection = new Mock(); mockConnection.Setup( c => c.InsertAsync(It.IsAny())) - .Callback(() => Task.Delay(Timeout.InfiniteTimeSpan).Wait()) + .Callback(() => Task.Delay(TimeSpan.FromDays(1)).Wait()) .Returns(TaskExtension.GetCompletedTask(1)); var storage = new Mobile.Storage.Storage(mockConnection.Object); - var countdownEvent = new CountdownEvent(2); - Func putTask = () => - { - countdownEvent.Signal(); - return storage.PutLogAsync(StorageTestChannelName, new TestLog()); - }; - Task.Run(putTask); - Task.Run(putTask); - - // Wait for tasks started and bit more. - countdownEvent.Wait(); - Task.Delay(100).Wait(); - var result = storage.Shutdown(TimeSpan.FromTicks(1)); + // Ignore warnings because we just want to "fire and forget" +#pragma warning disable 4014 + storage.PutLogAsync(StorageTestChannelName, new TestLog()); + storage.PutLogAsync(StorageTestChannelName, new TestLog()); +#pragma warning restore 4014 + var result = storage.Shutdown(TimeSpan.FromTicks(1)); Assert.IsFalse(result); } @@ -57,11 +50,16 @@ public void ShutdownSucceed() var mockConnection = new Mock(); mockConnection.Setup( c => c.InsertAsync(It.IsAny())) - .Callback(() => Task.Delay(TimeSpan.FromSeconds(2))) + .Callback(() => Task.Delay(TimeSpan.FromSeconds(2)).Wait()) .Returns(TaskExtension.GetCompletedTask(1)); var storage = new Mobile.Storage.Storage(mockConnection.Object); - Task.Run(() => storage.PutLogAsync(StorageTestChannelName, new TestLog())); - Task.Run(() => storage.PutLogAsync(StorageTestChannelName, new TestLog())); + + // Ignore warnings because we just want to "fire and forget" +#pragma warning disable 4014 + storage.PutLogAsync(StorageTestChannelName, new TestLog()); + storage.PutLogAsync(StorageTestChannelName, new TestLog()); +#pragma warning restore 4014 + var result = storage.Shutdown(TimeSpan.FromSeconds(100)); Assert.IsTrue(result); } From 7a6e0da2839390cf436af67c95ad6b249d76e132 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 25 May 2017 16:53:18 -0700 Subject: [PATCH 24/90] Remove task locks because they have been replaced --- .../Storage/TaskLock.cs | 22 ----- .../Storage/TaskLockSource.cs | 86 ------------------- 2 files changed, 108 deletions(-) delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLock.cs delete mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLock.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLock.cs deleted file mode 100644 index c0db956b9..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLock.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; - -namespace Microsoft.Azure.Mobile.Storage -{ - public partial class TaskLock : IDisposable - { - private readonly TaskLockSource _source; - - private TaskLock(TaskLockSource source) - { - _source = source; - } - - public void Dispose() - { - _source.TaskHandlerWasDisposed(); - } - } -} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs deleted file mode 100644 index 688491d27..000000000 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/TaskLockSource.cs +++ /dev/null @@ -1,86 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using System.Threading; -using System.Threading.Tasks; - -namespace Microsoft.Azure.Mobile.Storage -{ - public partial class TaskLock - { - public class TaskLockSource : IDisposable - { - private readonly object _lockObject = new object(); - private readonly SemaphoreSlim _taskSemaphore = new SemaphoreSlim(1); - private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1, 1); - private bool _isShutdown; - private int _numTasksRemaning; - - public bool Shutdown(TimeSpan timeout) - { - lock (_lockObject) - { - _isShutdown = true; - } - return _taskSemaphore.Wait(timeout); - } - - public TaskLock GetTaskLock() - { - lock (_lockObject) - { - if (_isShutdown) - { - throw new StorageException("Trying to execute task after shutdown requested"); - } - _numTasksRemaning++; - if (_taskSemaphore.CurrentCount == 1) - { - _taskSemaphore.Wait(); - } - } - _mutex.Wait(); - return new TaskLock(this); - } - - - public async Task GetTaskLockAsync() - { - lock (_lockObject) - { - if (_isShutdown) - { - throw new StorageException("Trying to execute task after shutdown requested"); - } - _numTasksRemaning++; - if (_taskSemaphore.CurrentCount == 1) - { - _taskSemaphore.Wait(); - } - } - await _mutex.WaitAsync().ConfigureAwait(false); - return new TaskLock(this); - } - - public void TaskHandlerWasDisposed() - { - _mutex.Release(); - lock (_lockObject) - { - _numTasksRemaning--; - if (_numTasksRemaning == 0 && _isShutdown && _taskSemaphore.CurrentCount == 0) - { - _taskSemaphore.Release(); - } - - } - } - - public void Dispose() - { - _taskSemaphore.Dispose(); - _mutex.Dispose(); - } - } - } -} \ No newline at end of file From 0e3ef17a081ab778cf5c0bd5908e5b082489f86c Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 25 May 2017 16:54:00 -0700 Subject: [PATCH 25/90] Add comment --- .../Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs index f0fb48225..50844155b 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Storage/Storage.cs @@ -32,6 +32,7 @@ internal class LogEntry private readonly Dictionary> _pendingDbIdentifierGroups = new Dictionary>(); private readonly HashSet _pendingDbIdentifiers = new HashSet(); + // Blocking collection is thread safe private readonly BlockingCollection _queue = new BlockingCollection(); /// From 9610057460263d05fbeca4a112913e552804fdb9 Mon Sep 17 00:00:00 2001 From: Alexander Chocron Date: Thu, 25 May 2017 16:56:33 -0700 Subject: [PATCH 26/90] Remove unused files from shared project --- .../Microsoft.Azure.Mobile.Windows.Shared.projitems | 2 -- 1 file changed, 2 deletions(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems index ce0956760..7c2e119fb 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Windows.Shared/Microsoft.Azure.Mobile.Windows.Shared.projitems @@ -25,8 +25,6 @@ - - From 6e2edd84f383fd7ba6bccbdd53660c2b415ccc8f Mon Sep 17 00:00:00 2001 From: Guillaume Perrot Date: Thu, 25 May 2017 19:26:09 -0700 Subject: [PATCH 27/90] Work in progress for custom properties for Xamarin --- .../Transforms/Metadata.xml | 2 + .../CustomProperties.cs | 69 ++++++++++++++ .../Microsoft.Azure.Mobile.Android.csproj | 3 +- .../MobileCenter.cs | 5 + .../CustomProperties.cs | 90 ++++++++++++++++++ .../Microsoft.Azure.Mobile.Shared.projitems | 1 + .../MobileCenter.cs | 9 ++ .../CustomProperties.cs | 92 +++---------------- .../MobileCenter.cs | 7 +- .../CustomProperties.cs | 51 ++++++++++ .../Microsoft.Azure.Mobile.csproj | 1 + .../Microsoft.Azure.Mobile/MobileCenter.cs | 4 + 12 files changed, 246 insertions(+), 88 deletions(-) create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Android/CustomProperties.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/CustomProperties.cs create mode 100644 SDK/MobileCenter/Microsoft.Azure.Mobile/CustomProperties.cs diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Transforms/Metadata.xml b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Transforms/Metadata.xml index 407b9d6c6..531924b74 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Transforms/Metadata.xml +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Transforms/Metadata.xml @@ -3,4 +3,6 @@ AndroidMobileCenter + public + AndroidCustomProperties \ No newline at end of file diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/CustomProperties.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/CustomProperties.cs new file mode 100644 index 000000000..0b26c6588 --- /dev/null +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/CustomProperties.cs @@ -0,0 +1,69 @@ +using System; +using Com.Microsoft.Azure.Mobile; +using Java.Lang; +using Java.Util; + +namespace Microsoft.Azure.Mobile +{ + public partial class CustomProperties + { + internal AndroidCustomProperties AndroidCustomProperties { get; } = new AndroidCustomProperties(); + + readonly DateTime _epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + + CustomProperties PlatformSet(string key, string value) + { + AndroidCustomProperties.Set(key, value); + return this; + } + + CustomProperties PlatformSet(string key, DateTime value) + { + AndroidCustomProperties.Set(key, new Date((long)value.ToUniversalTime().Subtract(_epoch).TotalMilliseconds)); + return this; + } + + + CustomProperties PlatformSet(string key, int value) + { + AndroidCustomProperties.Set(key, new Integer(value)); + return this; + } + + CustomProperties PlatformSet(string key, long value) + { + AndroidCustomProperties.Set(key, new Long(value)); + return this; + } + + CustomProperties PlatformSet(string key, float value) + { + AndroidCustomProperties.Set(key, new Float(value)); + return this; + } + + CustomProperties PlatformSet(string key, double value) + { + AndroidCustomProperties.Set(key, new Java.Lang.Double(value)); + return this; + } + + CustomProperties PlatformSet(string key, decimal value) + { + AndroidCustomProperties.Set(key, new Java.Lang.Double((double)value)); + return this; + } + + CustomProperties PlatformSet(string key, bool value) + { + AndroidCustomProperties.Set(key, value); + return this; + } + + CustomProperties PlatformClear(string key) + { + AndroidCustomProperties.Clear(key); + return this; + } + } +} diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Microsoft.Azure.Mobile.Android.csproj b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Microsoft.Azure.Mobile.Android.csproj index 7e3a83a76..959b8a4c7 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Microsoft.Azure.Mobile.Android.csproj +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Microsoft.Azure.Mobile.Android.csproj @@ -55,6 +55,7 @@ + @@ -68,7 +69,7 @@ Microsoft.Azure.Mobile.Android.Bindings - + - - - + + + - - - + + + - - - + + + From 509b6157d6a520795b8e3fb412e1ccd32542970d Mon Sep 17 00:00:00 2001 From: Guillaume Perrot Date: Fri, 9 Jun 2017 14:34:41 -0700 Subject: [PATCH 83/90] Enable background UWP push callback in demo --- Apps/Contoso.Forms.Demo/Contoso.Forms.Demo.UWP/App.xaml.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo.UWP/App.xaml.cs b/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo.UWP/App.xaml.cs index 7b21bb668..677f819b1 100644 --- a/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo.UWP/App.xaml.cs +++ b/Apps/Contoso.Forms.Demo/Contoso.Forms.Demo.UWP/App.xaml.cs @@ -9,6 +9,7 @@ using Windows.UI.Xaml.Navigation; using Microsoft.Azure.Mobile; using Microsoft.Azure.Mobile.Analytics; +using Microsoft.Azure.Mobile.Push; namespace Contoso.Forms.Demo.UWP { @@ -80,6 +81,8 @@ protected override void OnLaunched(LaunchActivatedEventArgs e) // Ensure the current window is active Window.Current.Activate(); } + + Push.CheckLaunchedFromNotification(e); } /// From f870d6b269e70afc48bac3c0ba96765442c397dd Mon Sep 17 00:00:00 2001 From: Ivan Matkov Date: Tue, 13 Jun 2017 13:16:17 +0300 Subject: [PATCH 84/90] Add tag "mobilecenter" to nuspecs --- nuget/MacMobileCenter.nuspec | 1 + nuget/MacMobileCenterAnalytics.nuspec | 1 + nuget/MacMobileCenterCrashes.nuspec | 1 + nuget/MacMobileCenterDistribute.nuspec | 1 + nuget/MacMobileCenterPush.nuspec | 1 + nuget/MobileCenter.nuspec | 1 + nuget/MobileCenterAnalytics.nuspec | 1 + nuget/MobileCenterCrashes.nuspec | 1 + nuget/MobileCenterDistribute.nuspec | 1 + nuget/MobileCenterPush.nuspec | 1 + nuget/WindowsMobileCenter.nuspec | 1 + nuget/WindowsMobileCenterAnalytics.nuspec | 1 + nuget/WindowsMobileCenterCrashes.nuspec | 1 + nuget/WindowsMobileCenterPush.nuspec | 1 + 14 files changed, 14 insertions(+) diff --git a/nuget/MacMobileCenter.nuspec b/nuget/MacMobileCenter.nuspec index 8d71fa8d2..ea2923d1c 100644 --- a/nuget/MacMobileCenter.nuspec +++ b/nuget/MacMobileCenter.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center. Common package for every Mobile Center service. This package contains the basic functionalities that all Mobile Center services use to communicate with the backend. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/MacMobileCenterAnalytics.nuspec b/nuget/MacMobileCenterAnalytics.nuspec index 82853f294..890422868 100644 --- a/nuget/MacMobileCenterAnalytics.nuspec +++ b/nuget/MacMobileCenterAnalytics.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Analytics package provides analytics capabilities for your mobile applications. This package contains functionalities to collect session, device properties, events etc… for your application. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/MacMobileCenterCrashes.nuspec b/nuget/MacMobileCenterCrashes.nuspec index 8907d8ffd..117982edb 100644 --- a/nuget/MacMobileCenterCrashes.nuspec +++ b/nuget/MacMobileCenterCrashes.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Crashes package provides crash reporting capabilities for your mobile applications. This package contains functionalities to collect crash reports for your application. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/MacMobileCenterDistribute.nuspec b/nuget/MacMobileCenterDistribute.nuspec index 9cd6b85dd..458993647 100644 --- a/nuget/MacMobileCenterDistribute.nuspec +++ b/nuget/MacMobileCenterDistribute.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Distribute package provides in-app update capabilities for your mobile applications. This package provides capability to display in-app updates to your app users when a new version of the application is released. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/MacMobileCenterPush.nuspec b/nuget/MacMobileCenterPush.nuspec index 2256c20ee..b2e7c0363 100644 --- a/nuget/MacMobileCenterPush.nuspec +++ b/nuget/MacMobileCenterPush.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Push package provides push notification capabilities for your mobile applications This package contains functionalities to send push notifications to users of your application from our portal Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/MobileCenter.nuspec b/nuget/MobileCenter.nuspec index 9a179f40f..8fbc5add7 100644 --- a/nuget/MobileCenter.nuspec +++ b/nuget/MobileCenter.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center. Common package for every Mobile Center service. This package contains the basic functionalities that all Mobile Center services use to communicate with the backend. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/MobileCenterAnalytics.nuspec b/nuget/MobileCenterAnalytics.nuspec index d9b604ee6..b35bf497c 100644 --- a/nuget/MobileCenterAnalytics.nuspec +++ b/nuget/MobileCenterAnalytics.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Analytics package provides analytics capabilities for your mobile applications. This package contains functionalities to collect session, device properties, events etc… for your application. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/MobileCenterCrashes.nuspec b/nuget/MobileCenterCrashes.nuspec index be97ad76d..b91d4b2e3 100644 --- a/nuget/MobileCenterCrashes.nuspec +++ b/nuget/MobileCenterCrashes.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Crashes package provides crash reporting capabilities for your mobile applications. This package contains functionalities to collect crash reports for your application. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/MobileCenterDistribute.nuspec b/nuget/MobileCenterDistribute.nuspec index 27741044f..50892bfc9 100644 --- a/nuget/MobileCenterDistribute.nuspec +++ b/nuget/MobileCenterDistribute.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Distribute package provides in-app update capabilities for your mobile applications. This package provides capability to display in-app updates to your app users when a new version of the application is released. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/MobileCenterPush.nuspec b/nuget/MobileCenterPush.nuspec index 566ea45e1..0aed4b246 100644 --- a/nuget/MobileCenterPush.nuspec +++ b/nuget/MobileCenterPush.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Push package provides push notification capabilities for your mobile applications This package contains functionalities to send push notifications to users of your application from our portal Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/WindowsMobileCenter.nuspec b/nuget/WindowsMobileCenter.nuspec index 76a9b45ee..2a3f0753d 100644 --- a/nuget/WindowsMobileCenter.nuspec +++ b/nuget/WindowsMobileCenter.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center. Common package for every Mobile Center service. This package contains the basic functionalities that all Mobile Center services use to communicate with the backend. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/WindowsMobileCenterAnalytics.nuspec b/nuget/WindowsMobileCenterAnalytics.nuspec index 3be37cc38..95332b39e 100644 --- a/nuget/WindowsMobileCenterAnalytics.nuspec +++ b/nuget/WindowsMobileCenterAnalytics.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Analytics package provides analytics capabilities for your mobile applications. This package contains functionalities to collect session, device properties, events etc… for your application. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/WindowsMobileCenterCrashes.nuspec b/nuget/WindowsMobileCenterCrashes.nuspec index 9249e5926..010243857 100644 --- a/nuget/WindowsMobileCenterCrashes.nuspec +++ b/nuget/WindowsMobileCenterCrashes.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Crashes package provides crash reporting capabilities for your mobile applications. This package contains functionalities to collect crash reports for your application. Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr diff --git a/nuget/WindowsMobileCenterPush.nuspec b/nuget/WindowsMobileCenterPush.nuspec index 525e6ce80..2d643b59d 100644 --- a/nuget/WindowsMobileCenterPush.nuspec +++ b/nuget/WindowsMobileCenterPush.nuspec @@ -8,6 +8,7 @@ Microsoft Visual Studio Mobile Center Push package provides push notification capabilities for your mobile applications This package contains functionalities to send push notifications to users of your application from our portal Copyright (c) Microsoft Corporation. All Rights Reserved. + mobilecenter https://aka.ms/telgml https://aka.ms/vbgfx2 https://aka.ms/xhh7sr From 808e5e47a26437156758f72291eb739e2bc4a1c8 Mon Sep 17 00:00:00 2001 From: Guillaume Perrot Date: Tue, 13 Jun 2017 18:13:52 -0700 Subject: [PATCH 85/90] Avoid duplicate start session when resuming with a log --- .../Channel/SessionTracker.cs | 1 + .../SessionTrackerTest.cs | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Channel/SessionTracker.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Channel/SessionTracker.cs index 1049ee21d..f26e913c6 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Channel/SessionTracker.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Windows.Shared/Channel/SessionTracker.cs @@ -138,6 +138,7 @@ private void SendStartSessionIfNeeded() _sid = Guid.NewGuid(); _sessions.Add(now, _sid.Value); _applicationSettings[StorageKey] = SessionsAsString(); + _lastQueuedLogTime = TimeHelper.CurrentTimeInMilliseconds(); var startSessionLog = new StartSessionLog { Sid = _sid }; _channel.EnqueueAsync(startSessionLog); } diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs index 874702cec..d66e169e9 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs @@ -55,6 +55,20 @@ public void ResumeAfterTimeout() _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Exactly(2)); } + [TestMethod] + public void ResumeAfterTimeoutAndSendEvent() + { + _sessionTracker.Resume(); + _sessionTracker.Pause(); + Task.Delay((int)SessionTracker.SessionTimeout).Wait(); + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Once()); + + _sessionTracker.Resume(); + _mockChannelGroup.Raise(group => group.EnqueuingLog += null, null, new EnqueuingLogEventArgs(new EventLog())); + + _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Exactly(2)); + } + /// /// Verify that after a pause that is not long enough to be a timeout, the session tracker does not send a start session log /// From 7e7262535a3641208a44d626ecbe040ecc61363c Mon Sep 17 00:00:00 2001 From: Guillaume Perrot Date: Wed, 14 Jun 2017 11:20:49 -0700 Subject: [PATCH 86/90] Add description for the new double session test --- .../SessionTrackerTest.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs index d66e169e9..183425999 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/SessionTrackerTest.cs @@ -55,6 +55,9 @@ public void ResumeAfterTimeout() _mockChannel.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Exactly(2)); } + /// + /// Verify that after a timeout, if we resume and send a log at the same time, only 1 new session is started + /// [TestMethod] public void ResumeAfterTimeoutAndSendEvent() { From e82b4f252b1d4b64afce72c526091de865b0d26a Mon Sep 17 00:00:00 2001 From: Guillaume Perrot Date: Mon, 19 Jun 2017 13:46:39 -0700 Subject: [PATCH 87/90] Update bindings to 0.10.0 --- build.cake | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.cake b/build.cake index 6bad61172..54b77ddbe 100644 --- a/build.cake +++ b/build.cake @@ -53,8 +53,8 @@ var ANDROID_ASSEMBLIES_FOLDER = TEMPORARY_PREFIX + "AndroidAssemblies"; var PCL_ASSEMBLIES_FOLDER = TEMPORARY_PREFIX + "PCLAssemblies"; // Native SDK versions -var ANDROID_SDK_VERSION = "0.9.1-4+2ff69ee"; -var IOS_SDK_VERSION = "0.9.0"; +var ANDROID_SDK_VERSION = "0.10.0"; +var IOS_SDK_VERSION = "0.10.0"; var PLATFORM_PATHS = new PlatformPaths(); From 846bcd35dbec339085db2ed6d0e5c304cf9f165e Mon Sep 17 00:00:00 2001 From: Guillaume Perrot Date: Mon, 19 Jun 2017 13:49:19 -0700 Subject: [PATCH 88/90] Remove visibility change now that custom properties API is public --- .../Transforms/Metadata.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Transforms/Metadata.xml b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Transforms/Metadata.xml index b80570ea5..f973d8f35 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Transforms/Metadata.xml +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Transforms/Metadata.xml @@ -3,6 +3,5 @@ AndroidMobileCenter - public AndroidCustomProperties \ No newline at end of file From d39a676754ab100154442c139f423dcd21ad3652 Mon Sep 17 00:00:00 2001 From: Guillaume Perrot Date: Mon, 19 Jun 2017 14:14:06 -0700 Subject: [PATCH 89/90] Version 0.13.0 --- Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml | 2 +- Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs | 4 ++-- .../Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml | 2 +- .../Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs | 4 ++-- .../Contoso.Forms.Puppet.UWP/Package.appxmanifest | 2 +- .../Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs | 2 +- Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist | 4 ++-- .../Contoso.Forms.Puppet/Properties/AssemblyInfo.cs | 4 ++-- Apps/Contoso.UWP.Puppet/Package.appxmanifest | 4 ++-- Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs | 2 +- Apps/Contoso.iOS.Puppet/Info.plist | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs | 4 ++-- SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs | 2 +- .../Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs | 4 ++-- Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs | 4 ++-- Tests/Droid/Properties/AndroidManifest.xml | 2 +- Tests/Droid/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 4 ++-- Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs | 4 ++-- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 2 +- Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest | 2 +- .../Properties/AssemblyInfo.cs | 2 +- .../Properties/AssemblyInfo.cs | 4 ++-- Tests/iOS/Info.plist | 4 ++-- 53 files changed, 94 insertions(+), 94 deletions(-) diff --git a/Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml b/Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml index 0e3c0f86c..43fb09c4b 100644 --- a/Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml +++ b/Apps/Contoso.Android.Puppet/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs b/Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs index b8356b0f5..4c57864bc 100644 --- a/Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.Android.Puppet/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml index 31d19995b..3d2ab585f 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs index c4f968866..df06d1af3 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.Droid/Properties/AssemblyInfo.cs @@ -19,8 +19,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Package.appxmanifest b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Package.appxmanifest index 601b410e4..fa0d972bd 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Package.appxmanifest +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Package.appxmanifest @@ -1,6 +1,6 @@ - + MobileCenter-Forms-UWP-Puppet diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs index 127402430..62611d626 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.UWP/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] [assembly: ComVisible(false)] diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist index fcf9df1ee..4da6fed31 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet.iOS/Info.plist @@ -5,9 +5,9 @@ CFBundleIdentifier com.microsoft.azure.mobile.xamarin.forms.puppet CFBundleShortVersionString - 0.12.1 + 0.13.0 CFBundleVersion - 0.12.1 + 0.13.0 LSRequiresIPhoneOS MinimumOSVersion diff --git a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Properties/AssemblyInfo.cs b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Properties/AssemblyInfo.cs index 874b3df37..3fb134912 100644 --- a/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.Forms.Puppet/Contoso.Forms.Puppet/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/Apps/Contoso.UWP.Puppet/Package.appxmanifest b/Apps/Contoso.UWP.Puppet/Package.appxmanifest index 59c7e85f1..cc31d5b90 100644 --- a/Apps/Contoso.UWP.Puppet/Package.appxmanifest +++ b/Apps/Contoso.UWP.Puppet/Package.appxmanifest @@ -1,6 +1,6 @@ - + - + MobileCenter-UWP-Puppet diff --git a/Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs b/Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs index 57623852b..aefa44549 100644 --- a/Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs +++ b/Apps/Contoso.UWP.Puppet/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] [assembly: ComVisible(false)] \ No newline at end of file diff --git a/Apps/Contoso.iOS.Puppet/Info.plist b/Apps/Contoso.iOS.Puppet/Info.plist index 9c022aef1..36e42e7ef 100644 --- a/Apps/Contoso.iOS.Puppet/Info.plist +++ b/Apps/Contoso.iOS.Puppet/Info.plist @@ -7,9 +7,9 @@ CFBundleIdentifier com.microsoft.azure.mobile.xamarin.puppet CFBundleShortVersionString - 0.12.1 + 0.13.0 CFBundleVersion - 0.12.1 + 0.13.0 LSRequiresIPhoneOS MinimumOSVersion diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Properties/AssemblyInfo.cs index 9bea918aa..3863c914b 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android.Bindings/Properties/AssemblyInfo.cs @@ -26,5 +26,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs index e0509eeb9..bf321e810 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Android/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs index bd3acdd13..b30ff5ee7 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.Shared/WrapperSdk.cs @@ -5,6 +5,6 @@ public static class WrapperSdk public const string Name = "mobilecenter.xamarin"; /* We can't use reflection for assemblyInformationalVersion on iOS with "Link All" optimization. */ - internal const string Version = "0.12.1-SNAPSHOT"; + internal const string Version = "0.13.0-SNAPSHOT"; } } diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs index d5b618b79..4971eb375 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.UWP/Properties/AssemblyInfo.cs @@ -25,7 +25,7 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] [assembly: ComVisible(false)] [assembly: InternalsVisibleTo("Microsoft.Azure.Mobile.Test.UWP")] \ No newline at end of file diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS.Bindings/Properties/AssemblyInfo.cs index a8eb8be4f..6d3af8635 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS.Bindings/Properties/AssemblyInfo.cs @@ -31,5 +31,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs index c02460393..6f91b6a74 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile.iOS/Properties/AssemblyInfo.cs @@ -23,5 +23,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenter/Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs b/SDK/MobileCenter/Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs index e5a4c86c7..4edb8de19 100644 --- a/SDK/MobileCenter/Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenter/Microsoft.Azure.Mobile/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android.Bindings/Properties/AssemblyInfo.cs index fdbe1c402..7bbba8663 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android.Bindings/Properties/AssemblyInfo.cs @@ -18,8 +18,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android/Properties/AssemblyInfo.cs index 240b4b7f5..cebf56c9c 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.Android/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/Properties/AssemblyInfo.cs index 22bf5ee63..53fe7e0ec 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.UWP/Properties/AssemblyInfo.cs @@ -29,6 +29,6 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] -[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] [assembly: ComVisible(false)] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS.Bindings/Properties/AssemblyInfo.cs index d5dd62122..d7d9d14c3 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS.Bindings/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS/Properties/AssemblyInfo.cs index cd44f038e..a14c7cda7 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics.iOS/Properties/AssemblyInfo.cs @@ -23,5 +23,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics/Properties/AssemblyInfo.cs b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics/Properties/AssemblyInfo.cs index a097e6066..d3c493203 100644 --- a/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterAnalytics/Microsoft.Azure.Mobile.Analytics/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android.Bindings/Properties/AssemblyInfo.cs index 1bab78c16..53fcbe731 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android.Bindings/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android/Properties/AssemblyInfo.cs index e4137d287..da8b41f39 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.Android/Properties/AssemblyInfo.cs @@ -26,5 +26,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.UWP/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.UWP/Properties/AssemblyInfo.cs index db479db27..53cb94a68 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.UWP/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.UWP/Properties/AssemblyInfo.cs @@ -29,6 +29,6 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] [assembly: ComVisible(false)] \ No newline at end of file diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS.Bindings/Properties/AssemblyInfo.cs index 760a1ed79..4d0d7b04e 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS.Bindings/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS/Properties/AssemblyInfo.cs index 7e1741559..6e9f05103 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes.iOS/Properties/AssemblyInfo.cs @@ -23,5 +23,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs index 16ea38feb..a84a7c0af 100644 --- a/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterCrashes/Microsoft.Azure.Mobile.Crashes/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android.Bindings/Properties/AssemblyInfo.cs index 558cf6878..5259047ce 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android.Bindings/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android/Properties/AssemblyInfo.cs index 38e209c28..7161301c9 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.Android/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS.Bindings/Properties/AssemblyInfo.cs index 832775dc8..81a7b9237 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS.Bindings/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS/Properties/AssemblyInfo.cs index 960b7f792..99de501c7 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute.iOS/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute/Properties/AssemblyInfo.cs b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute/Properties/AssemblyInfo.cs index 35301a476..58cef9a48 100644 --- a/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterDistribute/Microsoft.Azure.Mobile.Distribute/Properties/AssemblyInfo.cs @@ -25,5 +25,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android.Bindings/Properties/AssemblyInfo.cs index aedb30567..05cda7dbe 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android.Bindings/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android/Properties/AssemblyInfo.cs index e9152cc10..57bd450e0 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.Android/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Properties/AssemblyInfo.cs index 142053368..e45b88969 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.UWP/Properties/AssemblyInfo.cs @@ -28,6 +28,6 @@ [assembly: ReferenceAssembly] #endif [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] [assembly: ComVisible(false)] [assembly: InternalsVisibleTo("Microsoft.Azure.Mobile.Test.UWP")] \ No newline at end of file diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS.Bindings/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS.Bindings/Properties/AssemblyInfo.cs index 1fe553e3e..b0c87126d 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS.Bindings/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS.Bindings/Properties/AssemblyInfo.cs @@ -30,5 +30,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS/Properties/AssemblyInfo.cs index a94e4acae..61a848139 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push.iOS/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs index 96ba99a26..61c51d5e4 100644 --- a/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs +++ b/SDK/MobileCenterPush/Microsoft.Azure.Mobile.Push/Properties/AssemblyInfo.cs @@ -24,5 +24,5 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs b/Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs index 9abc3dff4..15e69edd8 100644 --- a/Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs +++ b/Tests/Contoso.Forms.Test/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/Tests/Droid/Properties/AndroidManifest.xml b/Tests/Droid/Properties/AndroidManifest.xml index 59eed5a90..85b0063e5 100644 --- a/Tests/Droid/Properties/AndroidManifest.xml +++ b/Tests/Droid/Properties/AndroidManifest.xml @@ -1,5 +1,5 @@ - + diff --git a/Tests/Droid/Properties/AssemblyInfo.cs b/Tests/Droid/Properties/AssemblyInfo.cs index 99d640649..5038d57f1 100644 --- a/Tests/Droid/Properties/AssemblyInfo.cs +++ b/Tests/Droid/Properties/AssemblyInfo.cs @@ -17,8 +17,8 @@ // and "{Major}.{Minor}.{Build}.*" will update just the revision. [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] // The following attributes are used to specify the signing key for the assembly, // if desired. See the Mono documentation for more information about signing. diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.NET/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Analytics.NET/Properties/AssemblyInfo.cs index 8146b9344..cc9afea57 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.NET/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.NET/Properties/AssemblyInfo.cs @@ -33,7 +33,7 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] [assembly: InternalsVisibleTo("Microsoft.Azure.Mobile.Analytics.Test.Windows")] \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Properties/AssemblyInfo.cs index c6a638a20..05646be5e 100644 --- a/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Analytics.Test.Windows/Properties/AssemblyInfo.cs @@ -16,5 +16,5 @@ // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs index 5e6c24176..22f39db4a 100644 --- a/Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.NET/Properties/AssemblyInfo.cs @@ -33,8 +33,8 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] [assembly: InternalsVisibleTo("Microsoft.Azure.Mobile.Test.Windows")] [assembly: InternalsVisibleTo("Microsoft.Azure.Mobile.Analytics.Test.Windows")] diff --git a/Tests/Microsoft.Azure.Mobile.Push.NET/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Push.NET/Properties/AssemblyInfo.cs index ea56acc5e..2267ebd67 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.NET/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Push.NET/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Properties/AssemblyInfo.cs index cdc6e3be4..c05c68cc9 100644 --- a/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Push.Test.Windows/Properties/AssemblyInfo.cs @@ -33,4 +33,4 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] diff --git a/Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest b/Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest index 50c2077ca..25bdd2236 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest +++ b/Tests/Microsoft.Azure.Mobile.Test.UWP/Package.appxmanifest @@ -7,7 +7,7 @@ + Version="0.13.0.0" /> diff --git a/Tests/Microsoft.Azure.Mobile.Test.UWP/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Test.UWP/Properties/AssemblyInfo.cs index 60830c180..f093ea803 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.UWP/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.UWP/Properties/AssemblyInfo.cs @@ -14,5 +14,5 @@ // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] +[assembly: AssemblyFileVersion("0.13.0.0")] [assembly: ComVisible(false)] \ No newline at end of file diff --git a/Tests/Microsoft.Azure.Mobile.Test.Windows/Properties/AssemblyInfo.cs b/Tests/Microsoft.Azure.Mobile.Test.Windows/Properties/AssemblyInfo.cs index 556c93726..a93dc079f 100644 --- a/Tests/Microsoft.Azure.Mobile.Test.Windows/Properties/AssemblyInfo.cs +++ b/Tests/Microsoft.Azure.Mobile.Test.Windows/Properties/AssemblyInfo.cs @@ -16,5 +16,5 @@ // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.0.0")] -[assembly: AssemblyFileVersion("0.12.1.0")] -[assembly: AssemblyInformationalVersion("0.12.1-SNAPSHOT")] +[assembly: AssemblyFileVersion("0.13.0.0")] +[assembly: AssemblyInformationalVersion("0.13.0-SNAPSHOT")] diff --git a/Tests/iOS/Info.plist b/Tests/iOS/Info.plist index 1559f75f0..2cf23c169 100644 --- a/Tests/iOS/Info.plist +++ b/Tests/iOS/Info.plist @@ -9,9 +9,9 @@ CFBundleIdentifier com.contoso.contoso-forms-test CFBundleShortVersionString - 0.12.1 + 0.13.0 CFBundleVersion - 0.12.1 + 0.13.0 LSRequiresIPhoneOS MinimumOSVersion From 3d2f6ff4f71788f308b3711e5123eceb0a2a4542 Mon Sep 17 00:00:00 2001 From: Guillaume Perrot Date: Mon, 19 Jun 2017 17:28:49 -0700 Subject: [PATCH 90/90] Embed iOS SDK 0.10.1 --- build.cake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.cake b/build.cake index 54b77ddbe..ddf4379f4 100644 --- a/build.cake +++ b/build.cake @@ -54,7 +54,7 @@ var PCL_ASSEMBLIES_FOLDER = TEMPORARY_PREFIX + "PCLAssemblies"; // Native SDK versions var ANDROID_SDK_VERSION = "0.10.0"; -var IOS_SDK_VERSION = "0.10.0"; +var IOS_SDK_VERSION = "0.10.1"; var PLATFORM_PATHS = new PlatformPaths();