private void CreateWithAsyncInit_CreateOnly(bool readOnly) { // create a new message with asynchronous initializer var message = LogFileMessage.CreateWithAsyncInit(readOnly, out _); CheckDefaultState(message, false, readOnly); // check that the message is marked for asynchronous initialization Assert.True(message.IsAsyncInitPending); // check whether the message reflects the desired read-only state Assert.Equal(readOnly, message.IsReadOnly); }
private async Task CreateWithAsyncInit_FollowedByInitialize(bool readOnly, bool initInSameThread, bool withPropertyChanged) { // create a new message with asynchronous initializer var message = LogFileMessage.CreateWithAsyncInit(readOnly, out var initializer); CheckDefaultState(message, false, readOnly); // checks IsInitialized // check that the message is marked for asynchronous initialization Assert.True(message.IsAsyncInitPending); // prepare data pulling some information out of the event handler SynchronizationContext handlerThreadSynchronizationContext = null; var changedPropertyNames = new List <string>(); var handlerCalledEvent = new ManualResetEventSlim(false); // the handler that is expected to be called on changes void PropertyChangedHandler(object sender, PropertyChangedEventArgs e) { handlerThreadSynchronizationContext = SynchronizationContext.Current; changedPropertyNames.Add(e.PropertyName); handlerCalledEvent.Set(); } // run test in a separate thread that provides a synchronization context that allows to // marshal calls into that thread await mThread.Factory.Run(() => { Assert.NotNull(SynchronizationContext.Current); }); // register the PropertyChanged event if (withPropertyChanged) { await mThread.Factory.Run(() => { message.PropertyChanged += PropertyChangedHandler; }); } // callback that initializes the message void InitializeTest() { initializer.Initialize( 1, DateTimeOffset.Parse("2020-01-01T12:00:00+01:00"), 2, 3, "Log Writer", "Log Level", new TagSet("Tag"), "Application", "Process", 42, "Some text"); // check administrative properties Assert.True(message.IsInitialized); Assert.False(message.IsAsyncInitPending); // check message properties Assert.Equal(1, message.Id); Assert.Equal(DateTimeOffset.Parse("2020-01-01T12:00:00+01:00"), message.Timestamp); Assert.Equal(2, message.HighPrecisionTimestamp); Assert.Equal(3, message.LostMessageCount); Assert.Equal("Log Writer", message.LogWriterName); Assert.Equal("Log Level", message.LogLevelName); Assert.Equal(new TagSet("Tag"), message.Tags); Assert.Equal("Application", message.ApplicationName); Assert.Equal("Process", message.ProcessName); Assert.Equal(42, message.ProcessId); Assert.Equal("Some text", message.Text); if (initInSameThread) { if (withPropertyChanged) { // the event handler should have been called only once in the same thread // (the event handler is called directly as the registering thread is the same as the thread raising the event) Assert.True(handlerCalledEvent.IsSet); Assert.Equal(new string[] { null }, changedPropertyNames.ToArray()); // null => all properties } else { // the event handler should not have been called Assert.False(handlerCalledEvent.IsSet); } } } // initialize the message either in the context of the thread that registered the handler // or in a different - the current - thread if (initInSameThread) { await mThread.Factory.Run(InitializeTest); } else { InitializeTest(); } if (!initInSameThread) { // the thread registering the event and the thread initializing the message are different if (withPropertyChanged) { // event handler should run in the context of the thread that registered it Assert.True(handlerCalledEvent.Wait(1000)); Assert.Same(mThread.Context.SynchronizationContext, handlerThreadSynchronizationContext); Assert.Equal(new string[] { null }, changedPropertyNames.ToArray()); } else { // the event handler should not have been called Assert.False(handlerCalledEvent.Wait(1000)); } } }