public static void GetActualType___Should_return_serialized_runtime_types___When_objects_were_serialized_using_mix_of_legacy_and_OBC_discriminator_conventions_and_method_is_called_on_current_payload_before_legacy_payload()
        {
            Action test = () =>
            {
                // Arrange
                var legacyPayload = "{ \"_t\" : \"ModelObjectForDiscriminatorConventionTest\", \"AbstractClass\" : { \"_t\" : \"ConcreteClassForDiscriminatorConventionTest\", \"StringProperty\" : \"my-string\", \"IntProperty\" : -392 } }";

                var currentPayload = "{ \"_t\" : \"OBeautifulCode.Serialization.Bson.Test.ObcBsonDiscriminatorConventionTest+ModelObjectForDiscriminatorConventionTest, OBeautifulCode.Serialization.Bson.Test\", \"AbstractClass\" : { \"_t\" : \"OBeautifulCode.Serialization.Bson.Test.ObcBsonDiscriminatorConventionTest+ConcreteClassForDiscriminatorConventionTest, OBeautifulCode.Serialization.Bson.Test\", \"StringProperty\" : \"my-string\", \"IntProperty\" : -392 } }";

                var serializer = new ObcBsonSerializer <TypesToRegisterBsonSerializationConfiguration <ModelObjectForDiscriminatorConventionTest> >();

                var expected = new ModelObjectForDiscriminatorConventionTest(new ConcreteClassForDiscriminatorConventionTest("my-string", -392));

                // Act
                var actual1 = serializer.Deserialize <ModelObjectForDiscriminatorConventionTest>(currentPayload);

                var actual2 = serializer.Deserialize <ModelObjectForDiscriminatorConventionTest>(legacyPayload);

                // Assert
                actual1.AsTest().Must().BeEqualTo(expected);
                actual2.AsTest().Must().BeEqualTo(expected);
            };

            test.ExecuteInNewAppDomain();
        }
        /// <inheritdoc />
        public override ISerializer BuildSerializer(
            SerializerRepresentation serializerRepresentation,
            AssemblyMatchStrategy assemblyMatchStrategy = AssemblyMatchStrategy.AnySingleVersion)
        {
            if (serializerRepresentation == null)
            {
                throw new ArgumentNullException(nameof(serializerRepresentation));
            }

            ISerializer result;

            if (CachedSerializerRepresentationToSerializerMap.TryGetValue(serializerRepresentation, out ConcurrentDictionary <AssemblyMatchStrategy, ISerializer> assemblyMatchStrategyToSerializerMap))
            {
                if (assemblyMatchStrategyToSerializerMap.TryGetValue(assemblyMatchStrategy, out result))
                {
                    return(result);
                }
            }

            // ReSharper disable once RedundantArgumentDefaultValue
            var configurationType = serializerRepresentation.SerializationConfigType?.ResolveFromLoadedTypes(assemblyMatchStrategy, throwIfCannotResolve: true);

            ISerializer serializer;

            switch (serializerRepresentation.SerializationKind)
            {
            case SerializationKind.Bson:
                serializer = new ObcBsonSerializer(configurationType?.ToBsonSerializationConfigurationType());
                break;

            case SerializationKind.Json:
                serializer = new ObcJsonSerializer(configurationType?.ToJsonSerializationConfigurationType());
                break;

            case SerializationKind.PropertyBag:
                serializer = new ObcPropertyBagSerializer(configurationType?.ToPropertyBagSerializationConfigurationType());
                break;

            default:
                throw new NotSupportedException(Invariant($"{nameof(serializerRepresentation)} from enumeration {nameof(SerializationKind)} of {serializerRepresentation.SerializationKind} is not supported."));
            }

            result = this.WrapInCompressingSerializerIfAppropriate(serializer, serializerRepresentation.CompressionKind);

            CachedSerializerRepresentationToSerializerMap.TryAdd(serializerRepresentation, new ConcurrentDictionary <AssemblyMatchStrategy, ISerializer>());

            CachedSerializerRepresentationToSerializerMap[serializerRepresentation].TryAdd(assemblyMatchStrategy, result);

            return(result);
        }
        public static void GetSerializationConfigurationInUseForDeserialization___Should_return_serialization_configuration_of_serializer_being_used_to_deserialize_payload___When_called()
        {
            // When the BSON serializer hits the AbstractClass property, it will call ObcBsonDiscriminatorConvention.GetActualType
            // which will de-reference ConcreteClassForThreadStaticTest and then check whether that type is registered by calling
            // GetSerializationConfigurationInUseForDeserialization().ThrowOnUnregisteredTypeIfAppropriate(), before it moves on.
            // We are using that to test whether the right serialization configuration is returned by running multiple parallel
            // de-serialization operations with a configuration that will throw and one that will not throw when checking
            // ConcreteClassForThreadStaticTest.
            Action test = () =>
            {
                // Arrange
                var payload = "{ \"_t\" : \"OBeautifulCode.Serialization.Bson.Test.ObcBsonSerializerTest+ModelObjectForThreadStaticTest, OBeautifulCode.Serialization.Bson.Test\", \"AbstractClass\" : { \"_t\" : \"OBeautifulCode.Serialization.Bson.Test.ObcBsonSerializerTest+ConcreteClassForThreadStaticTest, OBeautifulCode.Serialization.Bson.Test\", \"StringProperty\" : \"my-string\", \"IntProperty\" : -392 } }";

                var throwingSerializer = new ObcBsonSerializer <ThrowingSerializationConfigurationForThreadStaticTest>();

                var notThrowingSerializer = new ObcBsonSerializer <NotThrowingSerializationConfigurationForThreadStaticTest>();

                var expected = new ModelObjectForThreadStaticTest(new ConcreteClassForThreadStaticTest("my-string", -392));

                var parallelOptions = new ParallelOptions
                {
                    MaxDegreeOfParallelism = 10,
                };

                // Act
                Parallel.For(0, 1000, parallelOptions, index =>
                {
                    if ((index % 2) == 0)
                    {
                        var actual = Record.Exception(() => throwingSerializer.Deserialize <ModelObjectForThreadStaticTest>(payload));

                        // ReSharper disable once PossibleNullReferenceException
                        actual.InnerException.AsTest().Must().BeOfType <InvalidOperationException>();

                        // ReSharper disable once PossibleNullReferenceException
                        actual.InnerException.Message.Must().BeEqualTo("Attempted to perform operation on unregistered type 'ObcBsonSerializerTest.ConcreteClassForThreadStaticTest'.");
                    }
                    else
                    {
                        var actual = notThrowingSerializer.Deserialize <ModelObjectForThreadStaticTest>(payload);

                        actual.AsTest().Must().BeEqualTo(expected);
                    }
                });
            };

            test.ExecuteInNewAppDomain();
        }
        public static void ProcessDetails_Roundtrips()
        {
            // Arrange
            var expected       = A.Dummy <ProcessDetails>();
            var bsonSerializer = new ObcBsonSerializer(typeof(DiagnosticsBsonSerializationConfiguration).ToBsonSerializationConfigurationType());
            var jsonSerializer = new ObcJsonSerializer(typeof(DiagnosticsJsonSerializationConfiguration).ToJsonSerializationConfigurationType());

            // Act
            var actualBsonString = bsonSerializer.SerializeToString(expected);
            var actualBson       = bsonSerializer.Deserialize <ProcessDetails>(actualBsonString);

            var actualJsonString = jsonSerializer.SerializeToString(expected);
            var actualJson       = jsonSerializer.Deserialize <ProcessDetails>(actualJsonString);

            // Assert
            actualBson.Should().Be(expected);
            actualJson.Should().Be(expected);
        }
        public static void Roundtrip_DefaultPropertiesPackageDescription()
        {
            // Arrange
            var expected       = new PackageDescription();
            var bsonSerializer = new ObcBsonSerializer <PackagingBsonSerializationConfiguration>();
            var jsonSerializer = new ObcJsonSerializer <PackagingJsonSerializationConfiguration>();

            // Act
            var actualBsonString     = bsonSerializer.SerializeToString(expected);
            var actualFromBsonString = bsonSerializer.Deserialize <PackageDescription>(actualBsonString);

            var actualJsonString     = jsonSerializer.SerializeToString(expected);
            var actualFromJsonString = jsonSerializer.Deserialize <PackageDescription>(actualJsonString);

            // Assert
            actualFromBsonString.Should().Be(expected);
            actualFromJsonString.Should().Be(expected);
        }
        public static void Roundtrip_DummyPackageRepositoryConfiguration()
        {
            // Arrange
            var expected       = A.Dummy <PackageRepositoryConfiguration>();
            var bsonSerializer = new ObcBsonSerializer <PackagingBsonSerializationConfiguration>();
            var jsonSerializer = new ObcJsonSerializer <PackagingJsonSerializationConfiguration>();

            // Act
            var actualBsonString     = bsonSerializer.SerializeToString(expected);
            var actualFromBsonString = bsonSerializer.Deserialize <PackageRepositoryConfiguration>(actualBsonString);

            var actualJsonString     = jsonSerializer.SerializeToString(expected);
            var actualFromJsonString = jsonSerializer.Deserialize <PackageRepositoryConfiguration>(actualJsonString);

            // Assert
            actualFromBsonString.Should().Be(expected);
            actualFromJsonString.Should().Be(expected);
        }
        public static void Roundtrip_DummyScheduleBase()
        {
            // Arrange
            var expected       = A.Dummy <ScheduleBase>();
            var bsonSerializer = new ObcBsonSerializer <CronBsonSerializationConfiguration>();
            var jsonSerializer = new ObcJsonSerializer <CronJsonSerializationConfiguration>();

            // Act
            var actualBsonString     = bsonSerializer.SerializeToString(expected);
            var actualFromBsonString = bsonSerializer.Deserialize <ScheduleBase>(actualBsonString);

            var actualJsonString     = jsonSerializer.SerializeToString(expected);
            var actualFromJsonString = jsonSerializer.Deserialize <ScheduleBase>(actualJsonString);

            // Assert
            actualFromBsonString.Should().Be(expected);
            actualFromJsonString.Should().Be(expected);
        }