chr
2026-04-05 fe750b791d5b517cc4e9bc8e99a9a75139a0cfba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
//            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.ComponentModel;
using System.Globalization;
using System.Linq;
using System.Xml.Serialization;
using OpenTap.Translation;
 
namespace OpenTap
{
    /// <summary>
    /// Settings class containing user-configurable platform options.
    /// </summary>
    [Display("Engine", "Engine Settings")]
    [HelpLink(@"EditorHelp.chm::/Configurations/Engine Configuration.html")]
    public class EngineSettings : ComponentSettings<EngineSettings>
    {
        /// <summary>
        /// Enum to represent choices for <see cref="AbortTestPlan"/> setting.
        /// </summary>
        [Flags]
        public enum AbortTestPlanType
        {
            /// <summary> If a step completes with verdict 'Fail', the test plan execution should be aborted.</summary>
            [Display("Break On Fail", "Issue a break when step completes with verdict 'Fail'.")]
            Step_Fail = 1,
            /// <summary> If a step completes with verdict 'Error', the test plan execution should be aborted.</summary>
            [Display("Break On Error", "Issue a break when step completes with an error.")]
            Step_Error = 2,
            /// <summary> If a step completes with verdict 'Inconclusive', the test plan execution should be aborted. </summary>
            [Display("Break On Inconclusive", "Issue a break when step completes with an inconclusive verdict.")]
            Step_Inconclusive = 4,
            /// <summary> If a step completes with verdict 'Pass', the test plan execution should be aborted. </summary>
            [Display("Break On Pass", "Issue a break when step completes with a pass verdict.")]
            Step_Pass = 8,
        }
 
 
        /// <summary>
        /// Where the session logs are saved. Must be a valid path.
        /// </summary>
        [Display("Log Path", Group: "General", Order: 1, Description: "Where to save the session log file. This setting only takes effect after restart.")]
        [FilePath(FilePathAttribute.BehaviorChoice.Save)]
        [HelpLink(@"EditorHelp.chm::/Configurations/Using Tags and Variables in File Names.html")]
        public MacroString SessionLogPath { get; set; }
 
        /// <summary>
        /// Controls whether the engine should propagate a request for metadata.
        /// </summary>
        [Display("Allow Metadata Prompt", Group: "General", Order: 2, Description: "When the test plan starts, prompt the user for data specified by the plugin to associate with the results.")]
        public bool PromptForMetaData { get; set; }
 
        /// <summary>
        /// Configures the engine to stop the test plan run if a step fails or causes an error.  
        /// </summary>
        [Display("Test Plan Break Conditions", Group: "General", Order: 1, Description: "Specifies break conditions for the test plan execution. Break Conditions can also be specified on each test step.")]
        public AbortTestPlanType AbortTestPlan { get; set; }
 
        /// <summary>
        /// Gets or sets the limit for step runs to be added to the summary.
        /// </summary>
        [Display("Summary Test Step Limit", Group: "General", Order: 0,
            Description: "The maximum number of steps to include in the test plan summary")]
        public int SummaryTestStepLimit { get; set; } = 10_000;
 
        /// <summary>
        /// Name of the operator. This name will be saved along with the results.
        /// </summary>
        [Display("Name", Group: "Operator", Order: 20, Description: "Name of the operator. This name will be saved along with the results.")]
        [MetaData]
        public string OperatorName { get; set; }
 
        /// <summary>
        /// Name of the test station. This name will be saved along with the results.
        /// </summary>
        [Display("Station", Group: "Operator", Order: 21, Description: "Name of the test station. This name will be saved along with the results.")]
        [MetaData]
        public string StationName { get; set; }
 
        /// <summary>
        /// Gets or sets the maximum allowed latency for result propagation. When the limit is reached, the test plan run pauses while the results are propagated to the Result Listeners. 
        /// Result processing time is an estimated value based on previous processing delays.
        /// </summary>
        [Display("Result Latency Limit", Group: "Advanced", Collapsed: true, Order: 100.1, Description: "The maximum allowed latency for result propagation.  Reaching this limit will result in a temporary pause in the test plan while the results are being propagated to the ResultListeners. Result processing time is an estimated value based on previous processing delays.")]
        [Unit("s")]
        [Browsable(false)]
        public double ResultLatencyLimit { get; set; }
 
        /// <summary>
        /// True, if there is more than one log timestamping type.
        /// </summary>
        [XmlIgnore]
        [Browsable(false)]
        public bool HasMultipleTimestampers
        {
            get
            {
                return PluginManager.GetPlugins<Diagnostic.ILogTimestampProvider>().Count > 1;
            }
        }
 
        /// <summary>
        /// Sets the log timestamp mechanism.
        /// </summary>
        [Display("Log Timestamping", Group: "General", Order: 10, Description: "Which timestamping mechanism to use in the log.")]
        [PluginTypeSelector]
        [EnabledIf("HasMultipleTimestampers", true, HideIfDisabled = true)]
        public Diagnostic.ILogTimestampProvider LogTimestamper
        {
            get { return Log.Timestamper; }
            set { Log.Timestamper = value; }
        }
 
        /// <summary>
        /// Sets up some default values for the various settings.
        /// User code should use EngineSettings.Current to access the singleton instead of constructing a new object.
        /// </summary>
        public EngineSettings()
        {
            SessionLogPath = new MacroString { Text = "SessionLogs/SessionLog <Date>.txt" };
            ResultLatencyLimit = 3.0;
            OperatorName = Environment.GetEnvironmentVariable("USERNAME") ?? Environment.GetEnvironmentVariable("USER") ?? "";
            StationName = Environment.MachineName;
 
            // Set OpenTAP to abort on step error by default.
            AbortTestPlan = AbortTestPlanType.Step_Error;
 
            PromptForMetaData = false;
 
            ResourceManagerType = new ResourceTaskManager();
        }
 
        /// <summary> Where the test executive was started from. </summary>
        public static string StartupDir
        {
            get { return Environment.GetEnvironmentVariable("STARTUP_DIR"); }
            set { Environment.SetEnvironmentVariable("STARTUP_DIR", value); }
        }
 
        /// <summary>
        /// 
        /// </summary>
        [PluginTypeSelector]
        [Display("Resource Strategy", Group: "General", Order: 12, Description: "Selects which strategy to use for opening resources while the test plan is executing.")]
        public IResourceManager ResourceManagerType { get; set; }
 
        /// <summary> Loads a new working directory and sets up environment variables important to OpenTAP.</summary>
        /// <param name="newWorkingDirectory"></param>
        public static void LoadWorkingDirectory(string newWorkingDirectory)
        {
            EngineSettings.StartupDir = System.IO.Directory.GetCurrentDirectory();
            System.IO.Directory.SetCurrentDirectory(newWorkingDirectory);
        }
 
        static EngineSettings()
        {
            StartupDir = System.IO.Directory.GetCurrentDirectory();
            Environment.SetEnvironmentVariable("ENGINE_DIR", System.IO.Path.GetDirectoryName(typeof(TestPlan).Assembly.Location));
        }
 
        /// <summary>
        /// The currently selected language. Defaults to Invariant.
        /// </summary>
        [Browsable(false)]
        [XmlIgnore]
        public CultureInfo Language
        {
            get => language;
            set => language = value ?? throw new ArgumentNullException(nameof(value));
        }
        
        private CultureInfo language = TranslationManager.NeutralLanguage;
 
        /// <summary>
        /// The list of available languages. This is based on the currently installed .resx files.
        /// </summary>
        [Browsable(false)]
        [XmlIgnore]
        public IEnumerable<string> AvailableLanguages => TranslationManager.SupportedLanguages.Select(TranslationManager.CultureAsString);
 
        /// <summary>
        /// Whether or not the language selector should be visible.
        /// </summary>
        [Browsable(false)]
        [XmlIgnore]
        public bool LanguageSelectorEnabled => TranslationManager.SupportedLanguages.Any(x => !TranslationManager.NeutralLanguage.Equals(x));
 
        /// <summary>
        /// The currently selected language. Defaults to Invariant.
        /// </summary>
        [Display("Language", "The currently selected language.", Group: "Language", Order: 1000)]
        [AvailableValues(nameof(AvailableLanguages))]
        [EnabledIf(nameof(LanguageSelectorEnabled), HideIfDisabled = true)]
        public string LanguageString
        {
            get => TranslationManager.CultureAsString(Language);
            set
            {
                if (TranslationManager.SupportedLanguages.FirstOrDefault(x => TranslationManager.CultureAsString(x) == value) is { } newLanguage)
                    Language = newLanguage;
            }
        }
    }
}