// 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.IO; namespace OpenTap { #region Data structure /// /// A named object. /// public interface IAttributedObject { /// /// Name of this object. /// string Name { get; } /// /// String describing this object. /// string ObjectType { get; } } /// /// A named parameter. /// public interface IParameter : IAttributedObject { /// /// Optional name of the group of parameters to which this parameter belongs. /// string Group { get; } /// /// Value of this parameter. /// IConvertible Value { get; } } /// /// A list of parameters, with a string indexer. /// public interface IParameters : IList { /// /// Get a parameter by name. This can be the ObjectType or Name of a parameter. e.g "OpenTap.Unit" or just "Unit". /// /// Null if the parameter was not found IConvertible this[string Name] { get; } } /// /// An object in a hierarchy with a name and some named properties. /// public interface IData : IAttributedObject { /// /// Parent of this object. /// IData Parent { get; } /// /// All parameters that describes this object. /// IParameters Parameters { get; } /// /// Returns an ID that identifies this object. /// /// long GetID(); } /// /// Contains data that has the same table name, column names, and result data types as a . /// public interface IResultTable : IData { /// /// Array containing the result columns. /// IResultColumn[] Columns { get; } } /// /// Interface to store column data. /// public interface IResultColumn : IAttributedObject { /// /// Data in the column. /// Array Data { get; } } /// /// An "extensible Enum" that can be used to describe attachments. /// public class AttachmentType : IEquatable { #region Support private string _TypeName; /// /// Creates an attachment type object. /// public AttachmentType(string TypeName) { this._TypeName = TypeName; } /// /// Compares this object to another. /// bool IEquatable.Equals(AttachmentType other) { return _TypeName == other._TypeName; } /// /// Compares this object to another. /// public override bool Equals(object obj) { if (obj is AttachmentType) return _TypeName == ((AttachmentType)obj)._TypeName; else return false; } /// /// Returns the hashcode for this object. /// public override int GetHashCode() { return _TypeName.GetHashCode(); } #endregion /// /// A log file. /// public static AttachmentType LogFile { get { return new AttachmentType("LogFile"); } } /// /// A TestPlan XML file. /// public static AttachmentType TestPlan { get { return new AttachmentType("TestPlan"); } } } #endregion #region Searching /// /// The operation for . /// public enum ComparisonOperator { /// Two specified values must be the same. Equal, /// Two specified values must be different. NotEqual, /// Parameter must be less than. Less, /// Parameter must be less than or equal. LessEqual, /// Parameter must be greater than. Greater, /// Parameter must be greater than or equal. GreaterEqual, /// Parameter must be similar to the value. /// This is guaranteed to be true if the two values are equal, but is not otherwise guaranteed to work in any specific way. Like, /// /// Value must exist as a parameter name or value. /// Exists } /// /// Operation for . /// public enum LogicalOperator { /// /// Specifies that both conditions must be satisfied. /// And, /// /// Specifies that at least one of the two conditions must be satisfied. /// Or } /// /// The basic search operand from which the other search operands are derived. /// public abstract class SearchOperand { } /// Matches all children of the specified parents. public class SearchChildrenOf : SearchOperand { /// /// The list of elements to match the children of. /// public List Parents { get; set; } /// Matches all children of the specified parents. /// public SearchChildrenOf(List parents) { Parents = parents; } } /// /// Matches the last test plan run. /// public class SearchLastRun : SearchOperand { /// /// Number of the last runs to select. /// public int Count { get; } /// /// Matches the last test plan run. /// public SearchLastRun(int count = 1) { Count = count; } } /// A binary operation between two other operations. public class SearchCombinator : SearchOperand { /// /// Left-side operand. /// public SearchOperand A { get; } /// /// Operation to perform. /// public LogicalOperator Operator { get; } /// /// Right-side operand. /// public SearchOperand B { get; } /// A binary operation between two other operations. public SearchCombinator(SearchOperand a, LogicalOperator logicalOperator, SearchOperand b) { A = a; Operator = logicalOperator; B = b; } } /// /// Comparison between a named parameter and a value. /// public class SearchParameterValue : SearchOperand { /// /// Scope of the parameter to match ("", "plan", or "step"). /// public string Scope { get; } /// /// GroupName of the parameter to match (leave empty to match any group). /// public string Group { get;} /// /// Name of the parameter to match. /// public string Parameter { get;} /// /// Operation to perform. /// public ComparisonOperator CompareOperator { get;} /// /// Value to compare against the right-side value. /// public IConvertible Value { get; } /// Comparison between a named parameter and a value. /// /// /// /// /// public SearchParameterValue(string parameter, ComparisonOperator compareOperator, IConvertible value, string group = "", string scope = "") { Parameter = parameter; CompareOperator = compareOperator; Value = value; Group = group; Scope = scope; } } /// /// Comparison between a named parameter and a value. /// public class SearchRange : SearchOperand { /// /// The scope of the parameter to match. Could be "plan" or "step". /// public string Scope { get; set; } /// /// The name of the parameter to match. /// public string Parameter { get; set; } /// /// The value to compare against as the right-hand side. /// public ICombinedNumberSequence Value { get; set; } } /// /// The conditions for what to search for. /// public class SearchCondition { /// /// When true, specifies that any matched tree nodes automatically match all parents of that element. /// public bool GetParents { get; set; } /// /// When true, specifies that a matched tree root node automatically matches all children of that given element. /// public bool GetChildren { get; set; } /// /// The tree of conditions to match for. /// public SearchOperand Operation { get; set; } /// /// Condition that will match all elements in the result store. /// /// public static SearchCondition All() { return new SearchCondition { GetChildren = true, GetParents = true, Operation = null }; } /// /// Condition that will match any elements in a list as well as all children of those elements. /// /// public static SearchCondition ChildrenOf(IEnumerable testPlanRunIds) { return new SearchCondition { Operation = new SearchChildrenOf(testPlanRunIds.ToList()), GetChildren = true, GetParents = false }; } /// /// Condition that will match all elements in the result store. /// /// public static SearchCondition LastRun() { return new SearchCondition { GetChildren = true, GetParents = true, Operation = new SearchLastRun() }; } } #endregion /// /// A structure containing limit set data. /// public class LimitSet { /// /// The friendly name of the limit set. /// public string Name { get; private set; } /// /// The limits in this limit set. /// public List Limits { get; set; } /// /// Initializes a new instance of the class. /// /// public LimitSet(string name) { Name = name; Limits = new List(); } } /// /// A single limit from a limit set. /// public class Limit : ValidatingObject { /// /// The result name to match. /// [Display("Result Name", Description: "The name of the result to match.", Order: -10)] public string ResultName { get; set; } /// /// The result column to which the limits are applied. /// [Display("Column Name", Description: "The name of the result column to apply limit to.", Order: -9)] public string ColumnName { get; set; } /// /// The lower limit to apply to the result. /// [Display("Lower Limit", Description: "The lower limit. To pass the column value must be above this.", Order: -8)] public double LowerLimit { get; set; } /// /// The upper limit to apply to the result. /// [Display("Upper Limit", Description: "The upper limit. To pass the column value must be below this.", Order: -7)] public double UpperLimit { get; set; } /// /// The conditions that have to apply for this limit. /// [Display("Conditions", Description: "Additional conditions that apply for this limit. All conditions must evaluate to true for this limit to be used.", Order: -6)] public List Conditions { get; set; } /// /// Initializes a new instance of the class. /// public Limit() { Rules.Add(() => !string.IsNullOrWhiteSpace(ResultName), "Result Name must be valid.", "ResultName"); Rules.Add(() => !string.IsNullOrWhiteSpace(ColumnName), "Column Name must be valid.", "ColumnName"); Conditions = new List(); ResultName = ""; ColumnName = ""; } } /// /// A condition for a specific limit that must be satisfied for the limit to apply. /// public class LimitCondition : ValidatingObject { /// /// The result column name that this condition applies to. /// [Display("When Column", Description: "The condition value tested comes from the result column with this name.", Order: -3)] public string ColumnName { get; set; } /// /// The lower limit for this condition. /// [Display("Greater Than", Description: "The condition value must be above this value.", Order: -2)] public double LowerLimit { get; set; } /// /// The upper limit for this condition. /// [Display("Less Than", Description: "The condition value must be below this value.", Order: -1)] public double UpperLimit { get; set; } /// /// Returns a string describing this object. /// /// public override string ToString() { return String.Format("{0} < {1} < {2}", LowerLimit, ColumnName, UpperLimit); } /// /// Initializes a new instance of the class. /// public LimitCondition() { Rules.Add(() => !string.IsNullOrWhiteSpace(ColumnName), "Column Name must be valid.", "ColumnName"); } } /// /// Interface to results storage plugins. /// public interface IResultStore : IResource, ITapPlugin { /// /// Get list of properties on entries in the database which starts with a given string. /// The returned properties should be ordered by their frequency of use in the dataset. /// /// Only consider parameters from this scope. Could be "plan" or "step", or empty to consider all scopes. /// Only consider parameters from this parameter group. Can be empty to match any group. /// /// List GetProperties(string scope, string group, string startsWith, int limit); /// /// Gets all elements which match a given search condition. /// /// /// /// IEnumerable GetEntries(SearchCondition cond, List limitsets, bool withResults); /// /// Tries to delete the given entries and all sub entries. /// /// Entries to delete. bool DeleteEntries(IEnumerable entries); /// /// Returns all registered limit sets. /// List GetLimitSets(); /// /// Adds a limit set to the results store. /// /// void AddLimitSet(LimitSet limitSet); /// /// Deletes a limit set from the database. /// /// The name of the limit set to delete. void DeleteLimitSet(string Name); /// /// Returns the binary data for the given objects attachment, or null if it could not be found. /// /// /// byte[] GetAttachment(IData entry, AttachmentType attachmentType); /// /// Gets a list of attachments on the given object. /// /// List GetValidAttachments(IData entry); /// /// Returns the average duration of the last step runs with similar settings. /// /// /// TimeSpan? GetAverageDuration(TestStepRun step, int averageCount); /// /// Returns the average duration of the last PlanRuns runs with a similar plan. /// /// /// TimeSpan? GetAverageDuration(TestPlanRun plan, int averageCount); } /// /// IResultStore that supports attachment streams. /// public interface IAttachmentStream : IResultStore { /// /// Returns a stream that can read a given attachment entry. The returned stream must be disposed. /// /// /// Stream GetAttachmentStream(IData entry, AttachmentType attachmentType); } /// /// Interface to support result tagging in the OpenTAP Results Viewer. /// public interface IResultTagging : IResultStore { /// /// Add a TestPlan parameter to a number of TestPlans. /// void AddTestPlanRunParameter(IEnumerable PlanRunIDs, string Group, string ParameterName, IConvertible Value); /// /// Delete a TestPlan parameter from a number of TestPlans. /// void DeleteTestPlanRunParameter(IEnumerable PlanRunIDs, string Group, string ParameterName, IConvertible Value); /// /// Get distinct TestPlan parameter values ordered by popularity (number of uses). Optionally limited to Limit values, scope and group. /// IEnumerable GetTestPlanRunParameterValues(string ParameterName, string Scope = "", string Group = "", int Limit = -1); } /// /// Delegate that triggers notification updates when results are added to the store. /// public delegate void ResultUpdateEvent(object Sender); /// /// Interface to add notifications when the Results Viewer gets new data. /// public interface IResultStoreNotification : IResultStore { /// /// Event triggered when results are added to the store. /// event ResultUpdateEvent ResultUpdated; /// /// Event triggered when TestPlan or TestStep runs are added to the store. /// event ResultUpdateEvent RunsUpdated; /// /// Enables the Updated events. /// void EnableUpdateEvents(); /// /// Disables the Updated events. /// void DisableUpdateEvents(); } /// /// When implemented along with , this interface allows files with a given extension to be opened using your . /// It also can be used to allow the export of results to a file. /// public interface IFileResultStore { /// /// Gets or sets the currently chosen file. /// string FilePath { set; get; } /// /// Default extension without the dot (.) that files must match in order to load a file's results to Results Viewer (e.g. TapResults, not .TapResults). /// string DefaultExtension { get; } } }