Commit 901b0f7c authored by Asger Iversen's avatar Asger Iversen Committed by Rolf Madsen
Browse files

First source code drop. This corresponds to version 9.0.835-beta+8f8823e7

parents
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
*.sh binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
\ No newline at end of file
[Oo]bj
[Bb]in
*.suo
*.tss
/packages/
*.user
TestResults/
*.dat
.vs/
# Temp files from git merges:
*.orig
TestResult.xml
// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using System;
using System.ComponentModel;
namespace OpenTap.Plugins.BasicSteps
{
[Browsable(true)]
[Display("Delay", Group:"Basic Steps", Description: "Delays for a specified amount of time.")]
public class DelayStep : TestStep
{
[Display("Time Delay", Description: "The time to delay in the test step.")]
[Unit("s")]
public double DelaySecs {
get { return delaySecs; }
set
{
if (value >= 0.0)
delaySecs = value;
else throw new ArgumentException("Time Delay must be greater than 0 seconds.");
}
}
double delaySecs = 0.1; // Set to 100 ms just to show the syntax for a normal timespan with sub second precision in the property grid.
public override void Run()
{
TestPlan.Sleep(Time.FromSeconds(DelaySecs));
}
}
}
// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using OpenTap;
using System;
using System.Collections.Generic;
using System.Linq;
namespace OpenTap.Plugins.BasicSteps
{
public enum InputButtons
{
[Display("Ok / Cancel")]
OkCancel,
[Display("Yes / No")]
YesNo
}
public enum WaitForInputResult1
{
// The order of the results determines the order in which the buttons is shown in the dialog box.
// The number assigned, determines the default value.
No = 2, Yes = 1
}
public enum WaitForInputResult2
{
// The order of the results determines the order in which the buttons is shown in the dialog box.
// The number assigned, determines the default value.
Cancel = 2, Ok = 1
}
[Display("Dialog", Group: "Basic Steps", Description: "Used to interact with the user.")]
public class DialogStep : TestStep
{
[Display("Message", Description: "The message shown to the user.", Order: 0.1)]
public string Message { get; set; }
[Display("Title", "The title of the dialog box.", Order: 0)]
public string Title { get; set; }
[Display("Buttons", "Selects what buttons the user gets presented with.", Order: 0.2)]
public InputButtons Buttons { get; set; }
[Display("If Yes/OK", "This is the verdict presented when the user clicks \"Yes\" or \"OK\".", Group: "Verdict", Order: 0.3, Collapsed: true)]
public Verdict PositiveAnswer { get; set; }
[EnabledIf("Buttons", InputButtons.OkCancel, InputButtons.YesNo)]
[Display("If No/Cancel", "This is the verdict presented when the user clicks \"No\" or \"Cancel\".", Group: "Verdict", Order: 0.4, Collapsed: true)]
public Verdict NegativeAnswer { get; set; }
[Display("Use Timeout", "Enabling this will make the dialog close as if No/Cancel was clicked after an amount of time.", Group: "Timeout", Order: 1, Collapsed: true)]
public bool UseTimeout { get; set; }
double timeout = 5;
[EnabledIf("UseTimeout", true)]
[Unit("s")]
[Display("Timeout", "After this time the dialog will return the default answer.", Group: "Timeout", Order: 2, Collapsed: true)]
public double Timeout
{
get { return timeout; }
set
{
if (value >= 0)
timeout = value;
else throw new Exception("Timeout must be greater than 0 seconds.");
}
}
[EnabledIf("UseTimeout", true)]
[Display("Default Positive", "Is the default answer(on timeout) positive?", Group: "Timeout", Order: 2, Collapsed: true)]
public Verdict DefaultAnswer { get; set; }
public DialogStep()
{
Message = "Message";
Title = "Title";
Rules.Add(() => !string.IsNullOrWhiteSpace(Title), "Title is empty", Title);
Rules.Add(() => !string.IsNullOrWhiteSpace(Message), "Message is empty", Message);
}
public override void Run()
{
Verdict answer = DefaultAnswer;
try
{
var timeout = TimeSpan.FromSeconds(Timeout);
if (timeout == TimeSpan.Zero)
timeout = TimeSpan.FromSeconds(0.001);
if (Buttons == InputButtons.OkCancel)
{
var input = new PlatformRequest<WaitForInputResult2> { Message = Message };
var result = (PlatformRequest<WaitForInputResult2>)PlatformInteraction.WaitForInput(new List<IPlatformRequest> { input }, UseTimeout ? timeout : TimeSpan.Zero, Title: Title).First();
answer = result.Response == WaitForInputResult2.Ok ? PositiveAnswer : NegativeAnswer;
}
else
{
var input = new PlatformRequest<WaitForInputResult1> { Message = Message };
var result = (PlatformRequest<WaitForInputResult1>)PlatformInteraction.WaitForInput(new List<IPlatformRequest> { input }, UseTimeout ? timeout : TimeSpan.Zero, Title: Title).First();
answer = result.Response == WaitForInputResult1.Yes ? PositiveAnswer : NegativeAnswer;
}
}
catch (TimeoutException)
{
}
Verdict = answer;
}
}
}
// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using OpenTap;
using System.Collections.Generic;
namespace OpenTap.Plugins.BasicSteps
{
/// <summary>
/// Custom handler for exporting sweep parameters from a file.
/// </summary>
[Display("External Parameter Export")]
public interface ISweepValueExport : ITapPlugin
{
/// <summary>
/// The extension of the file including the '.'. For example '.zip'.
/// </summary>
string Extension { get; }
/// <summary>
/// Name of the file format. Shown when the user selects the format in the GUI.
/// For example, Compressed Using Zip.
/// </summary>
string Name { get; }
/// <summary>
/// Exports currently configured sweep parameters and values to a file
/// </summary>
/// <param name="parameters">The currently configured sweep loop parameters.</param>
/// <param name="parameterFilePath">Location of the file.</param>
void ExportSweepValues(List<SweepParam> parameters, string parameterFilePath);
}
}
// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using OpenTap;
using System.Collections.Generic;
namespace OpenTap.Plugins.BasicSteps
{
/// <summary>
/// Custom handler for importing sweep parameters from a file.
/// </summary>
[Display("Sweep Value Import")]
public interface ISweepValueImport : ITapPlugin
{
/// <summary>
/// The extension of the imported file including the '.'. For example '.zip'.
/// </summary>
string Extension { get; }
/// <summary>
/// Name of the file format. Shown when the user selects the format in the GUI.
/// For example, Compressed Using Zip.
/// </summary>
string Name { get; }
/// <summary>
/// Exports currently configured sweep values to a file.
/// </summary>
/// <param name="parameters">The currently configured sweep loop parameters.</param>
/// <param name="parameterFilePath">Location of the file.</param>
void ImportSweepValues(List<SweepParam> parameters, string parameterFilePath);
}
}
// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using System;
using System.Collections.Generic;
using System.Linq;
using System.ComponentModel;
using OpenTap; // Use Platform infrastructure/core components (log,TestStep definition, etc)
namespace OpenTap.Plugins.BasicSteps
{
[Display("If Verdict", Group: "Flow Control", Description: "Runs its child steps only when the verdict of another step has a specific value.")]
[AllowAnyChild]
public class IfStep : TestStep
{
public enum IfStepAction
{
[Display("Run Children")]
RunChildren,
[Display("Break Loop")]
BreakLoop,
[Display("Abort Test Plan")]
AbortTestPlan,
[Display("Wait For User")]
WaitForUser
}
#region Settings
[Display("If", Order: 1)]
public Input<Verdict> InputVerdict { get; set; }
[Display("Equals", Order: 2)]
public Verdict TargetVerdict { get; set; }
[Display("Then", Order: 3)]
public IfStepAction Action { get; set; }
#endregion
public IfStep()
{
InputVerdict = new Input<Verdict>();
}
public override void Run()
{
// Get the targetStep
if (InputVerdict == null)
throw new ArgumentException("Could not locate target test step");
var req = new PlatformRequest<WaitForInputResult1>() { Message = "Continue?" };
if (InputVerdict.Value == TargetVerdict)
{
switch (Action)
{
case IfStepAction.RunChildren:
Log.Info("Condition is true, running childSteps");
RunChildSteps();
break;
case IfStepAction.AbortTestPlan:
Log.Info("Condition is true, aborting TestPlan run.");
string msg = String.Format("TestPlan aborted by \"If\" Step ({2} of {0} was {1})", InputVerdict.Step.Name, InputVerdict.Value, InputVerdict.PropertyName);
throw new TestPlan.AbortException(msg);
case IfStepAction.WaitForUser:
Log.Info("Condition is true, waiting for user input.");
var res = PlatformInteraction.WaitForInput(new List<IPlatformRequest> { req }, TimeSpan.Zero).First();
var r = (WaitForInputResult1)res.Response;
if (r == WaitForInputResult1.No)
{
GetParent<TestPlan>().RequestAbort();
TestPlan.Sleep();
}
break;
case IfStepAction.BreakLoop:
Log.Info("Condition is true, breaking loop.");
var loopStep = GetParent<LoopTestStep>();
if(loopStep != null)
{
loopStep.BreakLoop();
}
break;
default:
throw new NotImplementedException();
}
}
else
{
Log.Info("Condition is false.");
}
}
}
}
// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using OpenTap;
using System;
using System.Globalization;
namespace OpenTap.Plugins.BasicSteps
{
/// <summary> Inputs that can be any numbers. </summary>
public class NumberInput : Input<IConvertible>, IInputTypeRestriction
{
/// <summary> Implementation of input type restrictions. This returns true if its a number type. </summary>
/// <param name="concreteType"></param>
/// <returns></returns>
public override bool SupportsType(Type concreteType)
{
if (!base.SupportsType(concreteType)) return false;
if (concreteType.IsEnum) return false;
if (concreteType.IsNumeric())
return true;
else
return false;
}
}
// TODO: deside if we want this step in (it is private for now)
[Display("Limit Check", Group: "Basic Steps", Description: "Checks the input if its within the specified limit. If Upper Limit and Lower Limit has the same value it is the same as checking for equality.")]
class LimitCheckStep: TestStep
{
[Display("Input Value", Order: 1, Description: "Value to be check within the limits.")]
public NumberInput InputValue { get; set; }
[Display("Upper Limit", Order: 2, Description: "Maximum limit to be check.")]
public Enabled<string> UpperLimit { get; set; }
[Display("Lower Limit", Order: 3, Description: "Minimum limit to be check.")]
public Enabled<string> LowerLimit { get; set; }
public LimitCheckStep()
{
LowerLimit = new Enabled<string> { Value = string.Empty };
UpperLimit = new Enabled<string> { Value = string.Empty };
string getError(Enabled<string> limit)
{
if (limit.IsEnabled)
{
if (string.IsNullOrWhiteSpace(limit.Value))
return "A numeric value is required.";
try
{
var nf = GetNumberFormatter();
if (nf.ParseNumber(limit.Value, typeof(IComparable)) == null)
return "Unable to parse number.";
}
catch(Exception ex)
{
return ex.Message;
}
}
return null;
}
Rules.Add(() => getError(UpperLimit) == null, () => getError(UpperLimit), nameof(UpperLimit));
Rules.Add(() => getError(LowerLimit) == null, () => getError(LowerLimit), nameof(LowerLimit));
Rules.Add(() => (UpperLimit.IsEnabled || LowerLimit.IsEnabled), "At least one limit must be enabled and contains a value.", nameof(LowerLimit), nameof(UpperLimit));
Rules.Add(() => InputValue?.Step != null && InputValue?.Property != null, "Input for limit check required.", nameof(InputValue));
Rules.Add(() =>
{
var nf = GetNumberFormatter();
IComparable parse(string val)
{
return (IComparable)nf.ParseNumber(val, typeof(IComparable));
}
IComparable upperLimit = infinity;
IComparable lowerLimit = negativeInfinity;
try
{
if (LowerLimit.IsEnabled && !string.IsNullOrWhiteSpace(LowerLimit.Value))
lowerLimit = parse(LowerLimit.Value);
if (UpperLimit.IsEnabled && !string.IsNullOrWhiteSpace(UpperLimit.Value))
upperLimit = parse(UpperLimit.Value);
return lowerLimit.CompareTo(upperLimit) <= 0;
}
catch
{
return false;
}
}, "Lower limit must be less than upper limit.", nameof(LowerLimit), nameof(UpperLimit));
}
NumberFormatter GetNumberFormatter()
{
UnitAttribute unit = null;
if (InputValue?.Property != null)
{
unit = InputValue.Property.GetAttribute<UnitAttribute>();
}
return new NumberFormatter(CultureInfo.CurrentCulture, unit);
}
static IComparable infinity,negativeInfinity;
static LimitCheckStep()
{
var nf = new NumberFormatter(CultureInfo.CurrentCulture);
IComparable parse(string val)
{
return (IComparable)nf.ParseNumber(val, typeof(IComparable));
}
infinity = parse("Infinity");
negativeInfinity = parse("-Infinity");
}
public override void Run()
{
var nf = GetNumberFormatter();
IComparable parse(string val)
{
return (IComparable)nf.ParseNumber(val, typeof(IComparable));
}
var inputvalue = parse(InputValue.Value.ToString(CultureInfo.CurrentCulture));
IComparable upperLimit = infinity;
IComparable lowerLimit = negativeInfinity;
if (LowerLimit.IsEnabled)
lowerLimit = parse(LowerLimit.Value);
if (UpperLimit.IsEnabled)
upperLimit = parse(UpperLimit.Value);
if(lowerLimit.CompareTo(upperLimit) > 0)
{
throw new InvalidOperationException("Lower limit must be bigger than upper limit");
}
var result = lowerLimit.CompareTo(inputvalue) <= 0 && upperLimit.CompareTo(inputvalue) >= 0;
if (result)
{
UpgradeVerdict(Verdict.Pass);
}
else
{
UpgradeVerdict(Verdict.Fail);
}
}
}
}
// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, you can obtain one at http://mozilla.org/MPL/2.0/.
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Threading;
using OpenTap;
namespace OpenTap.Plugins.BasicSteps
{
[Display("Lock", Group: "Flow Control", Description: "Locks the execution of child steps based on a specified mutex.")]
[AllowAnyChild]
public class LockStep : TestStep
{
public LockStep()
{
LockName = "TAP_Mutex1";
SystemWide = true;
Rules.Add(() => LockName.Contains("\\") == false, "Lock Name does not support '\\'", "LockName");
}
[Display("Lock Name", Description: "The name identifying the lock, used for sharing.")]
public string LockName { get; set; }
[Display("System Wide", Description: "Use a system-wide named mutex, that can be shared across processes.")]
public bool SystemWide { get; set; }
static ConcurrentDictionary<string, Mutex> localMutexes = new ConcurrentDictionary<string, Mutex>();
Mutex getMutex(string name, bool systemwide)
{
if (systemwide)
return new Mutex(false, name);
return localMutexes.GetOrAdd(name, s => new Mutex());
}
public override void Run()
{
Mutex mutex = getMutex(LockName, SystemWide);
mutex.WaitOne();
try
{
RunChildSteps();
}
finally
{
mutex.ReleaseMutex();
}
}
}
}
// Copyright Keysight Technologies 2012-2019
// This Source Code Form is subject to the terms of the Mozilla Public