Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skyline: Fixes to make TestAuditLogTutorial produce consistent screenshots #3316

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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