diff --git a/CHANGELOG.md b/CHANGELOG.md index 17dfa270e3..9544743c93 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - You should no longer pass `AndroidContext` as an argument to `SentrySdk.Init` ([#3562](https://github.com/getsentry/sentry-dotnet/pull/3562)) - The `SentryUser.Segment` property has been deprecated. Consider sending this as a tag or additional data instead ([#3563](https://github.com/getsentry/sentry-dotnet/pull/3563)) - The ITraceContext now includes an [Origin](https://develop.sentry.dev/sdk/telemetry/traces/trace-origin/), which is set automatically and is primarily used internally by the Sentry server ([#3564](https://github.com/getsentry/sentry-dotnet/pull/3564)) +- `Device.BatteryLevel` and `Device.ProcessorFrequency` are now stored as floats rather than ints, to align with the Cocoa and Java SDKs ([#3567](https://github.com/getsentry/sentry-dotnet/pull/3567)) ## 4.10.2 diff --git a/src/Sentry.Maui/Internal/MauiDeviceData.cs b/src/Sentry.Maui/Internal/MauiDeviceData.cs index 05c4b2efdf..3e92772ffa 100644 --- a/src/Sentry.Maui/Internal/MauiDeviceData.cs +++ b/src/Sentry.Maui/Internal/MauiDeviceData.cs @@ -40,7 +40,7 @@ public static void ApplyMauiDeviceData(this Device device, IDiagnosticLogger? lo try { var battery = Battery.Default; - device.BatteryLevel ??= battery.ChargeLevel < 0 ? null : (short)(battery.ChargeLevel * 100.0); + device.BatteryLevel ??= battery.ChargeLevel < 0 ? null : (float)(battery.ChargeLevel * 100.0); device.BatteryStatus ??= battery.State.ToString(); device.IsCharging ??= battery.State switch { diff --git a/src/Sentry/Platforms/Android/Extensions/DeviceExtensions.cs b/src/Sentry/Platforms/Android/Extensions/DeviceExtensions.cs index b608480191..d2aed064b7 100644 --- a/src/Sentry/Platforms/Android/Extensions/DeviceExtensions.cs +++ b/src/Sentry/Platforms/Android/Extensions/DeviceExtensions.cs @@ -23,7 +23,7 @@ public static void ApplyFromSentryAndroidSdk(this Device device, JavaSdk.Protoco device.Name ??= d.Name; device.Family ??= d.Family; device.ModelId ??= d.ModelId; - device.BatteryLevel ??= d.BatteryLevel?.ShortValue(); + device.BatteryLevel ??= d.BatteryLevel?.FloatValue(); device.IsCharging ??= d.IsCharging()?.BooleanValue(); device.IsOnline ??= d.IsOnline()?.BooleanValue(); device.Orientation ??= d.Orientation?.ToDeviceOrientation(); diff --git a/src/Sentry/Protocol/Device.cs b/src/Sentry/Protocol/Device.cs index 210aaf6a26..34a458f635 100644 --- a/src/Sentry/Protocol/Device.cs +++ b/src/Sentry/Protocol/Device.cs @@ -70,9 +70,9 @@ public sealed class Device : ISentryJsonSerializable, ICloneable, IUpdat public string? Architecture { get; set; } /// - /// If the device has a battery an integer defining the battery level (in the range 0-100). + /// If the device has a battery a number defining the battery level (in the range 0-100). /// - public short? BatteryLevel { get; set; } + public float? BatteryLevel { get; set; } /// /// True if the device is charging. @@ -184,7 +184,7 @@ public sealed class Device : ISentryJsonSerializable, ICloneable, IUpdat /// /// 2500 /// - public int? ProcessorFrequency { get; set; } + public float? ProcessorFrequency { get; set; } /// /// Kind of device the application is running on. @@ -426,15 +426,9 @@ public static Device FromJson(JsonElement json) var model = json.GetPropertyOrNull("model")?.GetString(); var modelId = json.GetPropertyOrNull("model_id")?.GetString(); var architecture = json.GetPropertyOrNull("arch")?.GetString(); - - // TODO: For next major: Remove this and change BatteryLevel from short to float - // The Java and Cocoa SDK report the battery as `float` - // Cocoa https://github.com/getsentry/sentry-cocoa/blob/e773cad622b86735f1673368414009475e4119fd/Sources/Sentry/include/SentryUIDeviceWrapper.h#L18 - // Java https://github.com/getsentry/sentry-java/blob/25f1ca4e1636a801c17c1662f0145f888550bce8/sentry/src/main/java/io/sentry/protocol/Device.java#L231-L233 var batteryLevel = json.GetPropertyOrNull("battery_level")?.TryGetDouble(out var level) is true - ? (short)level - : (short?)null; - + ? (float)level + : (float?)null; var isCharging = json.GetPropertyOrNull("charging")?.GetBoolean(); var isOnline = json.GetPropertyOrNull("online")?.GetBoolean(); var orientation = json.GetPropertyOrNull("orientation")?.GetString()?.ParseEnum(); @@ -453,14 +447,9 @@ public static Device FromJson(JsonElement json) var bootTime = json.GetPropertyOrNull("boot_time")?.GetDateTimeOffset(); var processorCount = json.GetPropertyOrNull("processor_count")?.GetInt32(); var cpuDescription = json.GetPropertyOrNull("cpu_description")?.GetString(); - - // TODO: For next major: Remove this and change ProcessorFrequency from int to float - // The Java SDK reports the processorFrequency as `double` - // Java https://github.com/getsentry/sentry-java/blob/9762f09afa51944b40a9b77e116a55e54636e6c5/sentry/src/main/java/io/sentry/protocol/Device.java#L130 var processorFrequency = json.GetPropertyOrNull("processor_frequency")?.TryGetDouble(out var frequency) is true - ? (int)frequency - : (int?)null; - + ? (float)frequency + : (float?)null; var deviceType = json.GetPropertyOrNull("device_type")?.GetString(); var batteryStatus = json.GetPropertyOrNull("battery_status")?.GetString(); var deviceUniqueIdentifier = json.GetPropertyOrNull("device_unique_identifier")?.GetString(); diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt index a147787b0d..95b72d1fb6 100644 --- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt +++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet6_0.verified.txt @@ -1588,7 +1588,7 @@ namespace Sentry.Protocol public const string Type = "device"; public Device() { } public string? Architecture { get; set; } - public short? BatteryLevel { get; set; } + public float? BatteryLevel { get; set; } public string? BatteryStatus { get; set; } public System.DateTimeOffset? BootTime { get; set; } public string? Brand { get; set; } @@ -1610,7 +1610,7 @@ namespace Sentry.Protocol public string? Name { get; set; } public Sentry.Protocol.DeviceOrientation? Orientation { get; set; } public int? ProcessorCount { get; set; } - public int? ProcessorFrequency { get; set; } + public float? ProcessorFrequency { get; set; } public float? ScreenDensity { get; set; } public int? ScreenDpi { get; set; } public string? ScreenResolution { get; set; } diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt index a147787b0d..95b72d1fb6 100644 --- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt +++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet7_0.verified.txt @@ -1588,7 +1588,7 @@ namespace Sentry.Protocol public const string Type = "device"; public Device() { } public string? Architecture { get; set; } - public short? BatteryLevel { get; set; } + public float? BatteryLevel { get; set; } public string? BatteryStatus { get; set; } public System.DateTimeOffset? BootTime { get; set; } public string? Brand { get; set; } @@ -1610,7 +1610,7 @@ namespace Sentry.Protocol public string? Name { get; set; } public Sentry.Protocol.DeviceOrientation? Orientation { get; set; } public int? ProcessorCount { get; set; } - public int? ProcessorFrequency { get; set; } + public float? ProcessorFrequency { get; set; } public float? ScreenDensity { get; set; } public int? ScreenDpi { get; set; } public string? ScreenResolution { get; set; } diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt index 24c0f6ba78..568ebe00f6 100644 --- a/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt +++ b/test/Sentry.Tests/ApiApprovalTests.Run.DotNet8_0.verified.txt @@ -1590,7 +1590,7 @@ namespace Sentry.Protocol public const string Type = "device"; public Device() { } public string? Architecture { get; set; } - public short? BatteryLevel { get; set; } + public float? BatteryLevel { get; set; } public string? BatteryStatus { get; set; } public System.DateTimeOffset? BootTime { get; set; } public string? Brand { get; set; } @@ -1612,7 +1612,7 @@ namespace Sentry.Protocol public string? Name { get; set; } public Sentry.Protocol.DeviceOrientation? Orientation { get; set; } public int? ProcessorCount { get; set; } - public int? ProcessorFrequency { get; set; } + public float? ProcessorFrequency { get; set; } public float? ScreenDensity { get; set; } public int? ScreenDpi { get; set; } public string? ScreenResolution { get; set; } diff --git a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt index 26f502c76e..b2873faa6d 100644 --- a/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt +++ b/test/Sentry.Tests/ApiApprovalTests.Run.Net4_8.verified.txt @@ -1586,7 +1586,7 @@ namespace Sentry.Protocol public const string Type = "device"; public Device() { } public string? Architecture { get; set; } - public short? BatteryLevel { get; set; } + public float? BatteryLevel { get; set; } public string? BatteryStatus { get; set; } public System.DateTimeOffset? BootTime { get; set; } public string? Brand { get; set; } @@ -1608,7 +1608,7 @@ namespace Sentry.Protocol public string? Name { get; set; } public Sentry.Protocol.DeviceOrientation? Orientation { get; set; } public int? ProcessorCount { get; set; } - public int? ProcessorFrequency { get; set; } + public float? ProcessorFrequency { get; set; } public float? ScreenDensity { get; set; } public int? ScreenDpi { get; set; } public string? ScreenResolution { get; set; } diff --git a/test/Sentry.Tests/Protocol/Context/DeviceTests.cs b/test/Sentry.Tests/Protocol/Context/DeviceTests.cs index 61cf719bf4..f891912702 100644 --- a/test/Sentry.Tests/Protocol/Context/DeviceTests.cs +++ b/test/Sentry.Tests/Protocol/Context/DeviceTests.cs @@ -3,6 +3,7 @@ namespace Sentry.Tests.Protocol.Context; public class DeviceTests { private readonly IDiagnosticLogger _testOutputLogger; + private const float Delta = 0.0001f; public DeviceTests(ITestOutputHelper output) { @@ -116,93 +117,28 @@ public void SerializeObject_AllPropertiesSetToNonDefault_SerializesValidObject() [Fact] public void Clone_CopyValues() { - var sut = new Device - { - Name = "name", - Brand = "brand", - Manufacturer = "manufacturer", - Family = "family", - Model = "Model", - ModelId = "ModelId", - Architecture = "Architecture", - BatteryLevel = 2, - IsCharging = false, - Orientation = DeviceOrientation.Portrait, - Simulator = true, - MemorySize = 3, - FreeMemory = 4, - UsableMemory = 5, - LowMemory = false, - StorageSize = 6, - FreeStorage = 7, - ExternalStorageSize = 8, - ExternalFreeStorage = 9, - ScreenResolution = "1x1", - ScreenDensity = 10, - ScreenDpi = 11, - BootTime = DateTimeOffset.UtcNow, - Timezone = TimeZoneInfo.Utc, - IsOnline = false, - ProcessorCount = 8, - CpuDescription = "Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz", - ProcessorFrequency = 2500, - DeviceType = "Console", - BatteryStatus = "Charging", - DeviceUniqueIdentifier = "d610540d-11d6-4daa-a98c-b71030acae4d", - SupportsVibration = false, - SupportsAccelerometer = true, - SupportsGyroscope = true, - SupportsAudio = true, - SupportsLocationService = true - }; + var sut = TestDevice(); var clone = sut.Clone(); - Assert.Equal(sut.Name, clone.Name); - Assert.Equal(sut.Family, clone.Family); - Assert.Equal(sut.Brand, clone.Brand); - Assert.Equal(sut.Manufacturer, clone.Manufacturer); - Assert.Equal(sut.Model, clone.Model); - Assert.Equal(sut.ModelId, clone.ModelId); - Assert.Equal(sut.Architecture, clone.Architecture); - Assert.Equal(sut.BatteryLevel, clone.BatteryLevel); - Assert.Equal(sut.IsCharging, clone.IsCharging); - Assert.Equal(sut.Orientation, clone.Orientation); - Assert.Equal(sut.Simulator, clone.Simulator); - Assert.Equal(sut.MemorySize, clone.MemorySize); - Assert.Equal(sut.FreeMemory, clone.FreeMemory); - Assert.Equal(sut.LowMemory, clone.LowMemory); - Assert.Equal(sut.UsableMemory, clone.UsableMemory); - Assert.Equal(sut.StorageSize, clone.StorageSize); - Assert.Equal(sut.FreeStorage, clone.FreeStorage); - Assert.Equal(sut.ExternalStorageSize, clone.ExternalStorageSize); - Assert.Equal(sut.ExternalFreeStorage, clone.ExternalFreeStorage); - Assert.Equal(sut.ScreenResolution, clone.ScreenResolution); - Assert.Equal(sut.ScreenDensity, clone.ScreenDensity); - Assert.Equal(sut.ScreenDpi, clone.ScreenDpi); - Assert.Equal(sut.BootTime, clone.BootTime); - Assert.Equal(sut.Timezone, clone.Timezone); - Assert.Equal(sut.IsOnline, clone.IsOnline); - Assert.Equal(sut.ProcessorCount, clone.ProcessorCount); - Assert.Equal(sut.CpuDescription, clone.CpuDescription); - Assert.Equal(sut.ProcessorFrequency, clone.ProcessorFrequency); - Assert.Equal(sut.DeviceType, clone.DeviceType); - Assert.Equal(sut.BatteryStatus, clone.BatteryStatus); - Assert.Equal(sut.DeviceUniqueIdentifier, clone.DeviceUniqueIdentifier); - Assert.Equal(sut.SupportsVibration, clone.SupportsVibration); - Assert.Equal(sut.SupportsAccelerometer, clone.SupportsAccelerometer); - Assert.Equal(sut.SupportsGyroscope, clone.SupportsGyroscope); - Assert.Equal(sut.SupportsAudio, clone.SupportsAudio); - Assert.Equal(sut.SupportsLocationService, clone.SupportsLocationService); + AssertAreEqual(sut, clone); } - [Theory] - [MemberData(nameof(TestCases))] - public void SerializeObject_TestCase_SerializesAsExpected((Device device, string serialized) @case) + [Fact] + public void WriteTo_FromJson_Symmetric() { - var actual = @case.device.ToJsonString(_testOutputLogger); + // Arrange + var sut = TestDevice(); - Assert.Equal(@case.serialized, actual); + var json = sut.ToJsonString(); + using var document = JsonDocument.Parse(json); + var jsonElement = document.RootElement; + + // Act + var result = Device.FromJson(jsonElement); + + // Assert + AssertAreEqual(result, sut); } [Fact] @@ -220,6 +156,43 @@ public void FromJson_NonSystemTimeZone_NoException() device.Timezone?.DisplayName.Should().Be("tz_name"); } + [Fact] + public void FromJson_BatteryLevelFloat() + { + // Arrange + const string json = """{"type":"device","battery_level":1.5}"""; + + // Act + var device = Json.Parse(json, Device.FromJson); + + // Assert + device.BatteryLevel.Should().NotBeNull(); + device.BatteryLevel?.Should().BeApproximately(1.5f, Delta); + } + + [Fact] + public void FromJson_ProcessorFrequencyFloat() + { + // Arrange + const string json = """{"type":"device","processor_frequency":2500.3}"""; + + // Act + var device = Json.Parse(json, Device.FromJson); + + // Assert + device.ProcessorFrequency.Should().NotBeNull(); + device.ProcessorFrequency?.Should().BeApproximately(2500.3f, Delta); + } + + [Theory] + [MemberData(nameof(TestCases))] + public void SerializeObject_TestCase_SerializesAsExpected((Device device, string serialized) @case) + { + var actual = @case.device.ToJsonString(_testOutputLogger); + + Assert.Equal(@case.serialized, actual); + } + public static IEnumerable TestCases() { yield return new object[] { (new Device(), """{"type":"device"}""") }; @@ -232,6 +205,7 @@ public static IEnumerable TestCases() yield return new object[] { (new Device { ModelId = "some model id" }, """{"type":"device","model_id":"some model id"}""") }; yield return new object[] { (new Device { Architecture = "some arch" }, """{"type":"device","arch":"some arch"}""") }; yield return new object[] { (new Device { BatteryLevel = 1 }, """{"type":"device","battery_level":1}""") }; + yield return new object[] { (new Device { BatteryLevel = 1.5f }, """{"type":"device","battery_level":1.5}""") }; yield return new object[] { (new Device { IsCharging = true }, """{"type":"device","charging":true}""") }; yield return new object[] { (new Device { IsOnline = true }, """{"type":"device","online":true}""") }; yield return new object[] { (new Device { Simulator = false }, """{"type":"device","simulator":false}""") }; @@ -252,6 +226,7 @@ public static IEnumerable TestCases() yield return new object[] { (new Device { ProcessorCount = 8 }, """{"type":"device","processor_count":8}""") }; yield return new object[] { (new Device { CpuDescription = "Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz" }, """{"type":"device","cpu_description":"Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz"}""") }; yield return new object[] { (new Device { ProcessorFrequency = 2500 }, """{"type":"device","processor_frequency":2500}""") }; + yield return new object[] { (new Device { ProcessorFrequency = 2500.5f }, """{"type":"device","processor_frequency":2500.5}""") }; yield return new object[] { (new Device { DeviceType = "Handheld" }, """{"type":"device","device_type":"Handheld"}""") }; yield return new object[] { (new Device { BatteryStatus = "Charging" }, """{"type":"device","battery_status":"Charging"}""") }; yield return new object[] { (new Device { DeviceUniqueIdentifier = "d610540d-11d6-4daa-a98c-b71030acae4d" }, """{"type":"device","device_unique_identifier":"d610540d-11d6-4daa-a98c-b71030acae4d"}""") }; @@ -261,4 +236,90 @@ public static IEnumerable TestCases() yield return new object[] { (new Device { SupportsAudio = true }, """{"type":"device","supports_audio":true}""") }; yield return new object[] { (new Device { SupportsLocationService = true }, """{"type":"device","supports_location_service":true}""") }; } + + private static Device TestDevice() + { + return new Device + { + Name = "name", + Brand = "brand", + Manufacturer = "manufacturer", + Family = "family", + Model = "Model", + ModelId = "ModelId", + Architecture = "Architecture", + BatteryLevel = 2, + IsCharging = false, + Orientation = DeviceOrientation.Portrait, + Simulator = true, + MemorySize = 3, + FreeMemory = 4, + UsableMemory = 5, + LowMemory = false, + StorageSize = 6, + FreeStorage = 7, + ExternalStorageSize = 8, + ExternalFreeStorage = 9, + ScreenResolution = "1x1", + ScreenDensity = 10, + ScreenDpi = 11, + BootTime = DateTimeOffset.UtcNow, + Timezone = TimeZoneInfo.Utc, + IsOnline = false, + ProcessorCount = 8, + CpuDescription = "Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz", + ProcessorFrequency = 2500, + DeviceType = "Console", + BatteryStatus = "Charging", + DeviceUniqueIdentifier = "d610540d-11d6-4daa-a98c-b71030acae4d", + SupportsVibration = false, + SupportsAccelerometer = true, + SupportsGyroscope = true, + SupportsAudio = true, + SupportsLocationService = true + }; + } + + private static void AssertAreEqual(Device actual, Device expected) + { + using (new AssertionScope()) + { + actual.Name.Should().Be(expected.Name); + actual.Manufacturer.Should().Be(expected.Manufacturer); + actual.Brand.Should().Be(expected.Brand); + actual.Architecture.Should().Be(expected.Architecture); + actual.BatteryLevel.Should().BeApproximately(expected.BatteryLevel, Delta); + actual.IsCharging.Should().Be(expected.IsCharging); + actual.IsOnline.Should().Be(expected.IsOnline); + actual.BootTime.Should().Be(expected.BootTime); + actual.ExternalFreeStorage.Should().Be(expected.ExternalFreeStorage); + actual.ExternalStorageSize.Should().Be(expected.ExternalStorageSize); + actual.ScreenResolution.Should().Be(expected.ScreenResolution); + actual.ScreenDensity.Should().Be(expected.ScreenDensity); + actual.ScreenDpi.Should().Be(expected.ScreenDpi); + actual.Family.Should().Be(expected.Family); + actual.FreeMemory.Should().Be(expected.FreeMemory); + actual.FreeStorage.Should().Be(expected.FreeStorage); + actual.MemorySize.Should().Be(expected.MemorySize); + actual.Model.Should().Be(expected.Model); + actual.ModelId.Should().Be(expected.ModelId); + actual.Orientation.Should().Be(expected.Orientation); + actual.Simulator.Should().Be(expected.Simulator); + actual.StorageSize.Should().Be(expected.StorageSize); + actual.Timezone.Should().Be(expected.Timezone); + actual.UsableMemory.Should().Be(expected.UsableMemory); + actual.LowMemory.Should().Be(expected.LowMemory); + actual.ProcessorCount.Should().Be(expected.ProcessorCount); + actual.CpuDescription.Should().Be(expected.CpuDescription); + actual.ProcessorFrequency.Should().BeApproximately(expected.ProcessorFrequency, Delta); + actual.SupportsVibration.Should().Be(expected.SupportsVibration); + actual.DeviceType.Should().Be(expected.DeviceType); + actual.BatteryStatus.Should().Be(expected.BatteryStatus); + actual.DeviceUniqueIdentifier.Should().Be(expected.DeviceUniqueIdentifier); + actual.SupportsAccelerometer.Should().Be(expected.SupportsAccelerometer); + actual.SupportsGyroscope.Should().Be(expected.SupportsGyroscope); + actual.SupportsAudio.Should().Be(expected.SupportsAudio); + actual.SupportsLocationService.Should().Be(expected.SupportsLocationService); + } + } } diff --git a/test/Sentry.Tests/Protocol/DeviceTests.cs b/test/Sentry.Tests/Protocol/DeviceTests.cs deleted file mode 100644 index cadb06d4f1..0000000000 --- a/test/Sentry.Tests/Protocol/DeviceTests.cs +++ /dev/null @@ -1,140 +0,0 @@ -namespace Sentry.Tests.Protocol; - -public class DeviceTests -{ - [Fact] - public void Clone_CopyValues() - { - // Arrange - var sut = TestDevice(); - - // Act - var result = sut.Clone(); - - // Assert - AssertAreEqual(result, sut); - } - - [Fact] - public void WriteTo_FromJson_Symmetric() - { - // Arrange - var sut = TestDevice(); - - var json = sut.ToJsonString(); - using var document = JsonDocument.Parse(json); - var jsonElement = document.RootElement; - - // Act - var result = Device.FromJson(jsonElement); - - // Assert - AssertAreEqual(result, sut); - } - - [Fact] - public void FromJson_JavaTypes_CastCorrectly() - { - // Arrange - var sut = TestDevice(); - - var json = sut.ToJsonString() - // In the Java SDK, the Processor Frequency is stored as a Double - .Replace(@"""processor_frequency"": 12", @"""processor_frequency"": 12.0"); - - using var document = JsonDocument.Parse(json); - var jsonElement = document.RootElement; - - // Act - var result = Device.FromJson(jsonElement); - - // Assert - AssertAreEqual(result, sut); - } - - private static Device TestDevice() - { - return new Device - { - Name = "TestName", - Manufacturer = "TestManufacturer", - Brand = "TestBrand", - Architecture = "TestArchitecture", - BatteryLevel = 1, - IsCharging = true, - IsOnline = true, - BootTime = new DateTimeOffset(2001, 06, 15, 12, 30, 0, TimeSpan.Zero), - ExternalFreeStorage = 2, - ExternalStorageSize = 3, - ScreenResolution = "800x600", - ScreenDensity = 1.2f, - ScreenDpi = 4, - Family = "TestFamily", - FreeMemory = 5, - FreeStorage = 6, - MemorySize = 7, - Model = "TestModel", - ModelId = "TestModelId", - Orientation = DeviceOrientation.Landscape, - Simulator = true, - StorageSize = 8, - Timezone = TimeZoneInfo.Utc, - UsableMemory = 9, - LowMemory = true, - ProcessorCount = 11, - CpuDescription = "TestCpuDescription", - ProcessorFrequency = 12, - SupportsVibration = true, - DeviceType = "TestDeviceType", - BatteryStatus = "TestBatteryStatus", - DeviceUniqueIdentifier = "TestDeviceUniqueIdentifier", - SupportsAccelerometer = true, - SupportsGyroscope = true, - SupportsAudio = true, - SupportsLocationService = true - }; - } - - private static void AssertAreEqual(Device actual, Device expected) - { - using (new AssertionScope()) - { - actual.Name.Should().Be(expected.Name); - actual.Manufacturer.Should().Be(expected.Manufacturer); - actual.Brand.Should().Be(expected.Brand); - actual.Architecture.Should().Be(expected.Architecture); - actual.BatteryLevel.Should().Be(expected.BatteryLevel); - actual.IsCharging.Should().Be(expected.IsCharging); - actual.IsOnline.Should().Be(expected.IsOnline); - actual.BootTime.Should().Be(expected.BootTime); - actual.ExternalFreeStorage.Should().Be(expected.ExternalFreeStorage); - actual.ExternalStorageSize.Should().Be(expected.ExternalStorageSize); - actual.ScreenResolution.Should().Be(expected.ScreenResolution); - actual.ScreenDensity.Should().Be(expected.ScreenDensity); - actual.ScreenDpi.Should().Be(expected.ScreenDpi); - actual.Family.Should().Be(expected.Family); - actual.FreeMemory.Should().Be(expected.FreeMemory); - actual.FreeStorage.Should().Be(expected.FreeStorage); - actual.MemorySize.Should().Be(expected.MemorySize); - actual.Model.Should().Be(expected.Model); - actual.ModelId.Should().Be(expected.ModelId); - actual.Orientation.Should().Be(expected.Orientation); - actual.Simulator.Should().Be(expected.Simulator); - actual.StorageSize.Should().Be(expected.StorageSize); - actual.Timezone.Should().Be(expected.Timezone); - actual.UsableMemory.Should().Be(expected.UsableMemory); - actual.LowMemory.Should().Be(expected.LowMemory); - actual.ProcessorCount.Should().Be(expected.ProcessorCount); - actual.CpuDescription.Should().Be(expected.CpuDescription); - actual.ProcessorFrequency.Should().Be(expected.ProcessorFrequency); - actual.SupportsVibration.Should().Be(expected.SupportsVibration); - actual.DeviceType.Should().Be(expected.DeviceType); - actual.BatteryStatus.Should().Be(expected.BatteryStatus); - actual.DeviceUniqueIdentifier.Should().Be(expected.DeviceUniqueIdentifier); - actual.SupportsAccelerometer.Should().Be(expected.SupportsAccelerometer); - actual.SupportsGyroscope.Should().Be(expected.SupportsGyroscope); - actual.SupportsAudio.Should().Be(expected.SupportsAudio); - actual.SupportsLocationService.Should().Be(expected.SupportsLocationService); - } - } -}