diff --git a/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs index 6f94e5ad2..48ccaee30 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Shared/AppCenter.cs @@ -60,24 +60,14 @@ namespace Microsoft.AppCenter /// public static LogLevel LogLevel { - get - { - return PlatformLogLevel; - } - - set - { - PlatformLogLevel = value; - } + get => PlatformLogLevel; + set => PlatformLogLevel = value; } /// /// Get the current version of AppCenter SDK. /// - public static string SdkVersion - { - get { return WrapperSdk.Version; } - } + public static string SdkVersion => WrapperSdk.Version; /// /// Check whether the SDK is enabled or not as a whole. diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs index 28620f906..8d57a92ff 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/AppCenter.cs @@ -37,6 +37,7 @@ namespace Microsoft.AppCenter private IChannelGroup _channelGroup; private IChannelUnit _channel; private readonly HashSet _services = new HashSet(); + private List _startedServiceNames; private string _logUrl; private bool _instanceConfigured; private string _appSecret; @@ -124,8 +125,7 @@ namespace Microsoft.AppCenter { lock (AppCenterLock) { - Instance.InstanceEnabled = enabled; - return Task.FromResult(default(object)); + return Instance.SetInstanceEnabled(enabled); } } @@ -261,34 +261,39 @@ namespace Microsoft.AppCenter internal IApplicationSettings ApplicationSettings => _applicationSettings; internal INetworkStateAdapter NetworkStateAdapter => _networkStateAdapter; - private bool InstanceEnabled + private bool InstanceEnabled => _applicationSettings.GetValue(EnabledKey, true); + + // That method isn't async itself but can return async task from the channel for awaiting log enqueue. + private Task SetInstanceEnabled(bool value) { - get + var enabledTerm = value ? "enabled" : "disabled"; + if (InstanceEnabled == value) { - return _applicationSettings.GetValue(EnabledKey, true); + AppCenterLog.Info(AppCenterLog.LogTag, $"App Center has already been {enabledTerm}."); + return Task.FromResult(default(object)); } - set + + // Update channels state. + _channelGroup?.SetEnabled(value); + + // Store state in the application settings. + _applicationSettings.SetValue(EnabledKey, value); + + // Apply change to services. + foreach (var service in _services) { - var enabledTerm = value ? "enabled" : "disabled"; - if (InstanceEnabled == value) - { - AppCenterLog.Info(AppCenterLog.LogTag, $"App Center has already been {enabledTerm}."); - return; - } - - // Update channels state. - _channelGroup?.SetEnabled(value); - - // Store state in the application settings. - _applicationSettings.SetValue(EnabledKey, value); - - // Apply change to services. - foreach (var service in _services) - { - service.InstanceEnabled = value; - } - AppCenterLog.Info(AppCenterLog.LogTag, $"App Center has been {enabledTerm}."); + service.InstanceEnabled = value; } + AppCenterLog.Info(AppCenterLog.LogTag, $"App Center has been {enabledTerm}."); + + // Send started services. + if (_startedServiceNames != null && value) + { + var startServiceLog = new StartServiceLog { Services = _startedServiceNames }; + _startedServiceNames = null; + return _channel.EnqueueAsync(startServiceLog); + } + return Task.FromResult(default(object)); } private void SetInstanceLogUrl(string logUrl) @@ -309,9 +314,7 @@ namespace Microsoft.AppCenter AppCenterLog.Error(AppCenterLog.LogTag, "Custom properties may not be null or empty"); return; } - var customPropertiesLog = new CustomPropertyLog(); - customPropertiesLog.Properties = customProperties.Properties; - _channel.EnqueueAsync(customPropertiesLog); + _channel.EnqueueAsync(new CustomPropertyLog { Properties = customProperties.Properties }); } private void OnUnhandledExceptionOccurred(object sender, UnhandledExceptionOccurredEventArgs args) @@ -362,7 +365,7 @@ namespace Microsoft.AppCenter throw new AppCenterException("App Center has not been configured."); } - var startServiceLog = new StartServiceLog(); + var serviceNames = new List(); foreach (var serviceType in services) { if (serviceType == null) @@ -385,7 +388,7 @@ namespace Microsoft.AppCenter throw new AppCenterException("Service type does not contain static 'Instance' property of type IAppCenterService"); } StartService(serviceInstance); - startServiceLog.Services.Add(serviceInstance.ServiceName); + serviceNames.Add(serviceInstance.ServiceName); } } catch (AppCenterException e) @@ -395,9 +398,20 @@ namespace Microsoft.AppCenter } // Enqueue a log indicating which services have been initialized - if (startServiceLog.Services.Count > 0) + if (serviceNames.Count > 0) { - _channel.EnqueueAsync(startServiceLog); + if (InstanceEnabled) + { + _channel.EnqueueAsync(new StartServiceLog { Services = serviceNames }); + } + else + { + if (_startedServiceNames == null) + { + _startedServiceNames = new List(); + } + _startedServiceNames.AddRange(serviceNames); + } } } diff --git a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Ingestion/Models/StartServiceLog.cs b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Ingestion/Models/StartServiceLog.cs index 89bf50f3a..232e44249 100644 --- a/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Ingestion/Models/StartServiceLog.cs +++ b/SDK/AppCenter/Microsoft.AppCenter.Windows.Shared/Ingestion/Models/StartServiceLog.cs @@ -36,7 +36,7 @@ namespace Microsoft.AppCenter.Ingestion.Models /// /// The list of services of the MobileCenter /// Start API call. - public StartServiceLog(Device device, System.DateTime? timestamp = default(System.DateTime?), System.Guid? sid = default(System.Guid?), IList services = default(IList)) + public StartServiceLog(Device device, DateTime? timestamp = default(DateTime?), Guid? sid = default(Guid?), IList services = default(IList)) : base(device, timestamp, sid) { Services = services; diff --git a/Tests/Microsoft.AppCenter.Test.Windows/AppCenterTest.cs b/Tests/Microsoft.AppCenter.Test.Windows/AppCenterTest.cs index cdc6b6ab1..9d8a20b36 100644 --- a/Tests/Microsoft.AppCenter.Test.Windows/AppCenterTest.cs +++ b/Tests/Microsoft.AppCenter.Test.Windows/AppCenterTest.cs @@ -1,4 +1,5 @@ using System; +using System.Threading.Tasks; using Microsoft.AppCenter.Channel; using Microsoft.AppCenter.Ingestion.Models; using Microsoft.AppCenter.Test.Channel; @@ -529,33 +530,68 @@ namespace Microsoft.AppCenter.Test { _settingsMock.Setup(settings => settings.GetValue(AppCenter.EnabledKey, It.IsAny())) .Returns(true); - var channelUnitMock = new Mock(); - _channelGroupMock.Setup( - group => group.AddChannel(It.IsAny(), It.IsAny(), It.IsAny(), It.IsAny())) - .Returns(channelUnitMock.Object); // Set before App Center is configured. AppCenter.SetCustomProperties(new CustomProperties()); - channelUnitMock.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); + _channelMock.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); AppCenter.Configure("appsecret"); // Set null. AppCenter.SetCustomProperties(null); - channelUnitMock.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); + _channelMock.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); // Set empty. var empty = new CustomProperties(); AppCenter.SetCustomProperties(empty); - channelUnitMock.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); + _channelMock.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); // Set normal. var properties = new CustomProperties(); properties.Set("test", "test"); AppCenter.SetCustomProperties(properties); - channelUnitMock.Verify(channel => channel.EnqueueAsync(It.Is(log => + _channelMock.Verify(channel => channel.EnqueueAsync(It.Is(log => log.Properties == properties.Properties)), Times.Once()); } + + /// + /// Verify sending start service log + /// + [TestMethod] + public void SendStartServices() + { + _settingsMock.Setup(settings => settings.GetValue(AppCenter.EnabledKey, It.IsAny())) + .Returns(true); + + AppCenter.Start("appsecret", typeof(MockAppCenterService)); + + Task.Delay(100).Wait(); + + _channelMock.Verify(channel => channel.EnqueueAsync(It.Is(log => + log.Services.Count == 1 && + log.Services[0] == MockAppCenterService.Instance.ServiceName)), Times.Once()); + } + + /// + /// Verify sending start services log after enable + /// + [TestMethod] + public void SendStartServicesAfterEnable() + { + _settingsMock.Setup(settings => settings.GetValue(AppCenter.EnabledKey, It.IsAny())) + .Returns(false); + + AppCenter.Start("appsecret", typeof(MockAppCenterService)); + Task.Delay(100).Wait(); + _channelMock.Verify(channel => channel.EnqueueAsync(It.IsAny()), Times.Never()); + + _settingsMock.SetupSequence(settings => settings.GetValue(AppCenter.EnabledKey, It.IsAny())) + .Returns(false).Returns(true); + AppCenter.SetEnabledAsync(true).RunNotAsync(); + _channelMock.Verify(channel => channel.EnqueueAsync(It.Is(log => + log.Services.Count == 1 && + log.Services[0] == MockAppCenterService.Instance.ServiceName)), Times.Once()); + } } public class NullInstanceAppCenterService : IAppCenterService