Skip to content

Commit

Permalink
Skyline: Fixes to make TestAuditLogTutorial produce consistent screen…
Browse files Browse the repository at this point in the history
…shots

- Fixed MultiFormActivator for ScreenshotPreviewForm
  • Loading branch information
brendanx67 committed Jan 3, 2025
1 parent 64137c6 commit 0bf065a
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 45 deletions.
26 changes: 20 additions & 6 deletions pwiz_tools/Skyline/Model/AuditLog/AuditLogEntry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,21 @@ public static MessageArgs DefaultSingular(object obj)
[XmlRoot(XML_ROOT)]
public class AuditLogEntry : Immutable, IXmlSerializable
{
public interface ITimeProvider
{
DateTime Now { get; }
}

/// <summary>
/// For consistent screenshots involving AuditLogEntries
/// </summary>
public static ITimeProvider TimeProvider { get; set; }

public static DateTime Now
{
get { return TimeProvider?.Now ?? DateTime.UtcNow; }
}

public const string XML_ROOT = "audit_log_entry";

private ImmutableList<DetailLogMessage> _allInfo;
Expand Down Expand Up @@ -904,7 +919,7 @@ public static AuditLogEntry ClearLogEntry(SrmDocument doc)
/// </summary>
public static AuditLogEntry CreateEmptyEntry()
{
return new AuditLogEntry(DateTime.UtcNow, string.Empty, SrmDocument.DOCUMENT_TYPE.none);
return new AuditLogEntry(Now, string.Empty, SrmDocument.DOCUMENT_TYPE.none);
}

/// <summary>
Expand Down Expand Up @@ -1015,7 +1030,7 @@ private static AuditLogEntry CreateCountChangeEntry(MessageType singular,
/// </summary>
public static AuditLogEntry CreateSingleMessageEntry(MessageInfo info, string extraInfo = null)
{
var result = new AuditLogEntry(DateTime.UtcNow, string.Empty, info.DocumentType, extraInfo)
var result = new AuditLogEntry(Now, string.Empty, info.DocumentType, extraInfo)
{
UndoRedo = info.ToMessage(LogLevel.undo_redo),
Summary = info.ToMessage(LogLevel.summary),
Expand Down Expand Up @@ -1103,8 +1118,7 @@ public static AuditLogEntry DiffDocNodes(MessageType action, SrmDocumentPair doc
Reflector<Targets>.EnumerateDiffNodes(objInfo, property, docType, false,
ignoreTransitions
? (Func<DiffNode, bool>) (node => !IsTransitionDiff(node.Property.PropertyType))
: null),
DateTime.UtcNow);
: null));

if (diffTree.Root != null)
{
Expand All @@ -1127,7 +1141,7 @@ public static AuditLogEntry DiffDocNodes(MessageType action, SrmDocumentPair doc
/// </summary>
public static AuditLogEntry CreateLogEnabledDisabledEntry(SrmDocument document)
{
var result = new AuditLogEntry(DateTime.UtcNow, string.Empty, document.DocumentType);
var result = new AuditLogEntry(Now, string.Empty, document.DocumentType);

var type = document.Settings.DataSettings.AuditLogging ? MessageType.log_enabled : MessageType.log_disabled;
var docType = document.DocumentType;
Expand Down Expand Up @@ -1635,7 +1649,7 @@ protected virtual AuditLogEntry CreateEntry(SrmDocumentPair docPair)
.ChangeRootObjectPair(docPair.ToObjectType());

var diffTree =
DiffTree.FromEnumerator(Reflector<T>.EnumerateDiffNodes(docPair.ToObjectType(), rootProp, docPair.OldDocumentType, (T)this), DateTime.UtcNow);
DiffTree.FromEnumerator(Reflector<T>.EnumerateDiffNodes(docPair.ToObjectType(), rootProp, docPair.OldDocumentType, (T)this));
if (diffTree.Root == null)
return baseEntry;

Expand Down
8 changes: 4 additions & 4 deletions pwiz_tools/Skyline/Model/AuditLog/DiffNode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -390,19 +390,19 @@ public DiffNodeNamePair ChangeName(PropertyName name)

public class DiffTree
{
public DiffTree(DiffNode root, DateTime? timeStamp = null)
public DiffTree(DiffNode root)
{
Root = root;
TimeStamp = timeStamp ?? DateTime.UtcNow;
TimeStamp = AuditLogEntry.Now;
}

public static DiffTree FromEnumerator(IEnumerator<DiffNode> treeEnumerator, DateTime? timeStamp = null)
public static DiffTree FromEnumerator(IEnumerator<DiffNode> treeEnumerator)
{
DiffNode current = null;
while (treeEnumerator.MoveNext())
current = treeEnumerator.Current;

return new DiffTree(current, timeStamp ?? DateTime.UtcNow);
return new DiffTree(current);
}

public DiffNode Root { get; private set; }
Expand Down
2 changes: 1 addition & 1 deletion pwiz_tools/Skyline/Model/AuditLog/ReflectorToString.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public static string ToString(ObjectPair<object> rootPair, SrmDocument.DOCUMENT_

var enumerator = EnumerateDiffNodes(objectInfo, rootProp, docType, true);

return ToString(objectInfo.ParentObjectPair, docType, DiffTree.FromEnumerator(enumerator, DateTime.UtcNow).Root, state);
return ToString(objectInfo.ParentObjectPair, docType, DiffTree.FromEnumerator(enumerator).Root, state);
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,18 @@ namespace TestRunnerLib.PInvoke
public static class User32TestExtensions
{
/// <summary>
/// Adjust z-order without activating
/// Adjust z-order without activating.
/// </summary>
public static void BringWindowToSameLevelWithoutActivating(this Form form, Form formInsertAfter)
/// <param name="form">The form for which to change z-order</param>
/// <param name="formInsertAfterHandle">The handle of the form to place the other form behind. It is important that this form is specified by its handle to avoid CrossThreadOperationException</param>
public static void BringWindowToSameLevelWithoutActivating(this Form form, IntPtr formInsertAfterHandle)
{
const User32.SetWindowPosFlags flags = User32.SetWindowPosFlags.NOMOVE |
User32.SetWindowPosFlags.NOSIZE |
User32.SetWindowPosFlags.NOACTIVATE |
User32.SetWindowPosFlags.SHOWWINDOW;

User32.SetWindowPos(form.Handle, formInsertAfter.Handle, 0, 0, 0, 0, flags);
User32.SetWindowPos(form.Handle, formInsertAfterHandle, 0, 0, 0, 0, flags);
}

public static void HideCaret(this ComboBox comboBox)
Expand Down
61 changes: 34 additions & 27 deletions pwiz_tools/Skyline/TestTutorial/AuditLogTutorialTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ public void TestAuditLogTutorial()
@"TestTutorial\AuditLogViews.zip"
};

AuditLogEntry.TimeProvider = new TestTimeProvider();

RunFunctionalTest();
}

Expand Down Expand Up @@ -149,14 +151,14 @@ protected override void DoTest()

RunUIForScreenShot(() => SkylineWindow.ShowUndo());
PauseForScreenShot("Undo list expanded.", 4, null, bmp =>
ClipBitmap(bmp, new Rectangle(0, 0, 713, 131)));
ClipBitmap(bmp.CleanupBorder(), new Rectangle(0, 0, 713, 131)));
RunUIForScreenShot(() => SkylineWindow.ShowUndo(false));

RunUI(SkylineWindow.Undo);

RunUIForScreenShot(() => SkylineWindow.ShowRedo());
PauseForScreenShot("Redo list expanded.", 5, null, bmp =>
ClipBitmap(bmp, new Rectangle(0, 0, 743, 127)));
ClipBitmap(bmp.CleanupBorder(), new Rectangle(0, 0, 743, 127)));
RunUIForScreenShot(() => SkylineWindow.ShowRedo(false));

RunUI(SkylineWindow.Redo);
Expand All @@ -169,11 +171,7 @@ protected override void DoTest()
var pasteDlg = ShowDialog<PasteDlg>(SkylineWindow.ShowPastePeptidesDlg);
RunUI(() => SetClipboardText("IEAIPQIDK\tGST-tag"));
RunUI(pasteDlg.PastePeptides);
RunUI(() =>
{
pasteDlg.Size = new Size(700, 210);
pasteDlg.Top = SkylineWindow.Bottom + 20;
});
RunUIForScreenShot(() => pasteDlg.Size = new Size(700, 210));
PauseForScreenShot<PasteDlg.PeptideListTab>("Insert Peptide List", 6);

using (new WaitDocumentChange())
Expand Down Expand Up @@ -390,7 +388,7 @@ protected override void DoTest()
RunUIForScreenShot(() => SkylineWindow.AuditLogForm.Parent.Parent.Width += 100); // Wider to remove the horizontal scrollbar
ShowReportsDropdown(AuditLogStrings.AuditLogForm_AuditLogForm_All_Info);
PauseForScreenShot<AuditLogForm>("Audit Log Reports menu", 16, null, bmp =>
ClipBitmap(bmp, new Rectangle(0, 0, 503, bmp.Height)));
ClipBitmap(bmp.CleanupBorder(true), new Rectangle(0, 0, 503, bmp.Height)));
HideReportsDropdown();

// TODO(nicksh): Audit log reason field does not currently support fill down
Expand Down Expand Up @@ -468,7 +466,7 @@ protected override void DoTest()
RunUIForScreenShot(() =>
{
var floatingForm = SkylineWindow.AuditLogForm.Parent.Parent;
floatingForm.Width = 1130; // Wider for Skyline Version and User columns
floatingForm.Width = 1140; // Wider for Skyline Version and User columns
floatingForm.Height += 10; // Extra for 2-line headers
});
PauseForScreenShot<AuditLogForm>("Audit Log with custom view.", 18);
Expand Down Expand Up @@ -561,25 +559,16 @@ private static void ShowAndPositionAuditLog(bool verticalScrollbar, int messageE
if (Program.SkylineOffscreen)
return;

const int timeExtra = 10;
const int spacing = 20;
int formWidth = 772 + messageExtra;
int formWidth = 772 + messageExtra + timeExtra;
if (verticalScrollbar)
formWidth += spacing;
RunUI(() =>
{
var floatingWindow = auditLogForm.Parent.Parent;
floatingWindow.Size = new Size(formWidth, height ?? 354);
var screen = Screen.FromControl(SkylineWindow);
if (screen.Bounds.Right > SkylineWindow.Right + spacing + floatingWindow.Width)
{
floatingWindow.Top = SkylineWindow.Top;
floatingWindow.Left = SkylineWindow.Right + spacing;
}
else
{
floatingWindow.Top = SkylineWindow.Bottom + spacing;
floatingWindow.Left = (screen.Bounds.Left + screen.Bounds.Right) / 2 - floatingWindow.Width / 2;
}
auditLogForm.DataGridView.Columns[0].Width += timeExtra;
if (messageExtra > 0)
{
var pathMessage = PropertyPath.Parse("Details!*.AllInfoMessage");
Expand Down Expand Up @@ -620,12 +609,6 @@ private void ShowLastExtraInfo(string message, int? pageNum = null)

var extraInfoDialog = ShowDialog<AuditLogExtraInfoForm>(() =>
((TextImageCell)SkylineWindow.AuditLogForm.DataGridView.Rows[0].Cells[1]).ClickImage(0));
RunUI(() =>
{
var logFloatingWindow = SkylineWindow.AuditLogForm.Parent.Parent;
extraInfoDialog.Left = logFloatingWindow.Left;
extraInfoDialog.Top = logFloatingWindow.Bottom + 20;
});
PauseForScreenShot<AuditLogExtraInfoForm>(message, pageNum);
OkDialog(extraInfoDialog, extraInfoDialog.OkDialog);
}
Expand Down Expand Up @@ -670,4 +653,28 @@ private void PanoramaSetup()
}
}
}

public class TestTimeProvider : AuditLogEntry.ITimeProvider
{
private readonly DateTime _startTime;
private TimeSpan _elapsedTime = TimeSpan.Zero;
private Random _random = new Random(1); // A consistent random series

public TestTimeProvider()
{
// Start with a consistent local time of 2025-1-1 at 9:35 AM
var localTime = new DateTime(2025, 1, 1, 9, 35, 0, DateTimeKind.Local);
// The audit logging system expects a UTC time.
_startTime = localTime.ToUniversalTime();
}

public DateTime Now
{
get
{
_elapsedTime += TimeSpan.FromSeconds(_random.Next(2, 10)); // Random time from 2 to 10 seconds
return _startTime.Add(_elapsedTime);
}
}
}
}
11 changes: 8 additions & 3 deletions pwiz_tools/Skyline/TestUtil/MultiFormActivator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,16 +98,21 @@ private void FormActivated(object sender, EventArgs e)
if (!activatedForm.IsHandleCreated)
return;

// Record the handle value for the activated form while on its thread.
// It will not be possible to get this handle from the Form object on
// any other thread without causing a CrossThreadOperationException
var activatedFormHandle = activatedForm.Handle;

lock (_formsToActivate)
{
foreach (var form in _formsToActivate.Where(form => !ReferenceEquals(form, activatedForm)))
{
ActionUtil.RunAsync(() => ShowForm(form, activatedForm));
ActionUtil.RunAsync(() => ShowForm(form, activatedFormHandle));
}
}
}

private void ShowForm(Form form, Form referenceForm)
private void ShowForm(Form form, IntPtr referenceFormHandle)
{
if (!form.IsHandleCreated)
return;
Expand All @@ -116,7 +121,7 @@ private void ShowForm(Form form, Form referenceForm)
form.Invoke((Action)(() =>
{
if (form.Visible)
form.BringWindowToSameLevelWithoutActivating(referenceForm);
form.BringWindowToSameLevelWithoutActivating(referenceFormHandle);
}));
}

Expand Down
17 changes: 16 additions & 1 deletion pwiz_tools/Skyline/TestUtil/ScreenshotPreviewForm.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
using System.Net;
using System.Threading;
using System.Windows.Forms;
using DigitalRune.Windows.Docking;
using pwiz.Skyline.Alerts;
using pwiz.Skyline.Util;
using pwiz.Skyline.Util.Extensions;
Expand Down Expand Up @@ -190,11 +191,25 @@ public void ShowOrUpdate()

// Ideally, this would use FormUtil.OpenForms, but this works pretty well and including
// all open forms gets tricky with cross-thread operations and choosing top level forms
_activator.Reset(this, _pauseTestController.ScreenshotControl.FindForm());
var activationForm = ActivationForm;
_activator.Reset(this, activationForm);
if (activationForm is FloatingWindow)
_activator.AddForm(activationForm.Owner); // Add the SkylineWindow too

FormStateChangedBackground();
}

private Form ActivationForm
{
get
{
var parentForm = _pauseTestController.ScreenshotControl.FindForm();
if (parentForm is DockableForm dockableForm) // A dockable form is never the top level
parentForm = dockableForm.Pane.FindForm();
return parentForm;
}
}

protected override bool ShowWithoutActivation
{
get { return true; } // Don't take activation away from SkylineWindow
Expand Down

0 comments on commit 0bf065a

Please sign in to comment.