| // <copyright file="EnvironmentManager.cs" company="Selenium Committers"> |
| // Licensed to the Software Freedom Conservancy (SFC) under one |
| // or more contributor license agreements. See the NOTICE file |
| // distributed with this work for additional information |
| // regarding copyright ownership. The SFC licenses this file |
| // to you under the Apache License, Version 2.0 (the |
| // "License"); you may not use this file except in compliance |
| // with the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, |
| // software distributed under the License is distributed on an |
| // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| // KIND, either express or implied. See the License for the |
| // specific language governing permissions and limitations |
| // under the License. |
| // </copyright> |
| |
| using Bazel; |
| using Newtonsoft.Json; |
| using NUnit.Framework; |
| using OpenQA.Selenium.Internal; |
| using System; |
| using System.IO; |
| using System.Linq; |
| using System.Runtime.InteropServices; |
| |
| namespace OpenQA.Selenium.Environment; |
| |
| public class EnvironmentManager |
| { |
| private static EnvironmentManager instance; |
| private Type driverType; |
| private Browser browser; |
| private IWebDriver driver; |
| private UrlBuilder urlBuilder; |
| private TestWebServer webServer; |
| private DriverFactory driverFactory; |
| private RemoteSeleniumServer remoteServer; |
| private string remoteCapabilities; |
| |
| private EnvironmentManager() |
| { |
| string dataFilePath; |
| Runfiles runfiles = null; |
| try |
| { |
| runfiles = Runfiles.Create(); |
| dataFilePath = runfiles.Rlocation("_main/dotnet/test/common/appconfig.json"); |
| } |
| catch (FileNotFoundException) |
| { |
| dataFilePath = "appconfig.json"; |
| } |
| string currentDirectory = this.CurrentDirectory; |
| |
| string content = File.ReadAllText(dataFilePath); |
| TestEnvironment env = JsonConvert.DeserializeObject<TestEnvironment>(content); |
| |
| string activeDriverConfig = System.Environment.GetEnvironmentVariable("ACTIVE_DRIVER_CONFIG") ?? TestContext.Parameters.Get("ActiveDriverConfig", env.ActiveDriverConfig); |
| string driverServiceLocation = System.Environment.GetEnvironmentVariable("DRIVER_SERVICE_LOCATION") ?? TestContext.Parameters.Get("DriverServiceLocation", env.DriverServiceLocation); |
| |
| string browserLocation = System.Environment.GetEnvironmentVariable("BROWSER_LOCATION") ?? TestContext.Parameters.Get("BrowserLocation", string.Empty); |
| |
| string activeWebsiteConfig = TestContext.Parameters.Get("ActiveWebsiteConfig", env.ActiveWebsiteConfig); |
| DriverConfig driverConfig = env.DriverConfigs[activeDriverConfig]; |
| WebsiteConfig websiteConfig = env.WebSiteConfigs[activeWebsiteConfig]; |
| |
| int port = PortUtilities.FindFreePort(); |
| websiteConfig.Port = port.ToString(); |
| |
| TestWebServerConfig webServerConfig = env.TestWebServerConfig; |
| webServerConfig.CaptureConsoleOutput = TestContext.Parameters.Get<bool>("CaptureWebServerOutput", env.TestWebServerConfig.CaptureConsoleOutput); |
| webServerConfig.HideCommandPromptWindow = TestContext.Parameters.Get<bool>("HideWebServerCommandPrompt", env.TestWebServerConfig.HideCommandPromptWindow); |
| webServerConfig.JavaHomeDirectory = TestContext.Parameters.Get("WebServerJavaHome", env.TestWebServerConfig.JavaHomeDirectory); |
| webServerConfig.Port = websiteConfig.Port; |
| |
| this.driverFactory = new DriverFactory(driverServiceLocation, browserLocation); |
| this.driverFactory.DriverStarting += OnDriverStarting; |
| |
| // Search for the driver type in the all assemblies, |
| // bazel uses unpredictable assembly names to execute tests |
| driverType = AppDomain.CurrentDomain.GetAssemblies() |
| .Reverse() |
| .Select(assembly => assembly.GetType(driverConfig.DriverTypeName)) |
| .FirstOrDefault(t => t != null); |
| |
| if (driverType == null) |
| { |
| throw new ArgumentOutOfRangeException($"Unable to find driver type {driverConfig.DriverTypeName}"); |
| } |
| |
| browser = driverConfig.BrowserValue; |
| remoteCapabilities = driverConfig.RemoteCapabilities; |
| |
| urlBuilder = new UrlBuilder(websiteConfig); |
| |
| // When run using the `bazel test` command, the following environment |
| // variable will be set. If not set, we're running from a build system |
| // outside Bazel, and need to locate the directory containing the jar. |
| string projectRoot = System.Environment.GetEnvironmentVariable("TEST_SRCDIR"); |
| if (string.IsNullOrEmpty(projectRoot)) |
| { |
| // Walk up the directory tree until we find ourselves in a directory |
| // where the path to the Java web server can be determined. |
| bool continueTraversal = true; |
| DirectoryInfo info = new DirectoryInfo(currentDirectory); |
| while (continueTraversal) |
| { |
| if (info == info.Root) |
| { |
| break; |
| } |
| |
| foreach (var childDir in info.EnumerateDirectories()) |
| { |
| // Case 1: The current directory of this assembly is in the |
| // same direct sub-tree as the Java targets (usually meaning |
| // executing tests from the same build system as that which |
| // builds the Java targets). |
| // If we find a child directory named "java", then the web |
| // server should be able to be found under there. |
| if (string.Compare(childDir.Name, "java", StringComparison.OrdinalIgnoreCase) == 0) |
| { |
| continueTraversal = false; |
| break; |
| } |
| |
| // Case 2: The current directory of this assembly is a different |
| // sub-tree as the Java targets (usually meaning executing tests |
| // from a different build system as that which builds the Java |
| // targets). |
| // If we travel to a place in the tree where there is a child |
| // directory named "bazel-bin", the web server should be found |
| // in the "java" subdirectory of that directory. |
| if (string.Compare(childDir.Name, "bazel-bin", StringComparison.OrdinalIgnoreCase) == 0) |
| { |
| string javaOutDirectory = Path.Combine(childDir.FullName, "java"); |
| if (Directory.Exists(javaOutDirectory)) |
| { |
| info = childDir; |
| continueTraversal = false; |
| break; |
| } |
| } |
| } |
| |
| if (continueTraversal) |
| { |
| info = info.Parent; |
| } |
| } |
| |
| projectRoot = info.FullName; |
| } |
| else |
| { |
| projectRoot += "/_main"; |
| } |
| |
| // Find selenium-manager binary. |
| try |
| { |
| string managerFilePath = ""; |
| runfiles ??= Runfiles.Create(); |
| |
| if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) |
| { |
| managerFilePath = runfiles.Rlocation("_main/dotnet/src/webdriver/manager/windows/selenium-manager.exe"); |
| } |
| else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) |
| { |
| managerFilePath = runfiles.Rlocation("_main/dotnet/src/webdriver/manager/linux/selenium-manager"); |
| } |
| else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) |
| { |
| managerFilePath = runfiles.Rlocation("_main/dotnet/src/webdriver/manager/macos/selenium-manager"); |
| } |
| |
| System.Environment.SetEnvironmentVariable("SE_MANAGER_PATH", managerFilePath); |
| } |
| catch (FileNotFoundException) |
| { |
| // Use the default one. |
| } |
| |
| webServer = new TestWebServer(projectRoot, webServerConfig); |
| bool autoStartRemoteServer = false; |
| if (browser == Browser.Remote) |
| { |
| autoStartRemoteServer = driverConfig.AutoStartRemoteServer; |
| } |
| |
| remoteServer = new RemoteSeleniumServer(projectRoot, autoStartRemoteServer); |
| } |
| |
| ~EnvironmentManager() |
| { |
| if (remoteServer != null) |
| { |
| remoteServer.StopAsync().Wait(); |
| } |
| if (webServer != null) |
| { |
| webServer.StopAsync().Wait(); |
| } |
| CloseCurrentDriver(); |
| } |
| |
| public event EventHandler<DriverStartingEventArgs> DriverStarting; |
| |
| public static EnvironmentManager Instance |
| { |
| get |
| { |
| if (instance == null) |
| { |
| instance = new EnvironmentManager(); |
| } |
| |
| return instance; |
| } |
| } |
| |
| public Browser Browser |
| { |
| get { return browser; } |
| } |
| |
| public string CurrentDirectory |
| { |
| get |
| { |
| string assemblyLocation = Path.GetDirectoryName(typeof(EnvironmentManager).Assembly.Location); |
| string testDirectory = TestContext.CurrentContext.TestDirectory; |
| if (assemblyLocation != testDirectory) |
| { |
| return assemblyLocation; |
| } |
| return testDirectory; |
| } |
| } |
| |
| public TestWebServer WebServer |
| { |
| get { return webServer; } |
| } |
| |
| public RemoteSeleniumServer RemoteServer |
| { |
| get { return remoteServer; } |
| } |
| |
| public string RemoteCapabilities |
| { |
| get { return remoteCapabilities; } |
| } |
| |
| public UrlBuilder UrlBuilder |
| { |
| get |
| { |
| return urlBuilder; |
| } |
| } |
| |
| public IWebDriver GetCurrentDriver() |
| { |
| if (driver != null) |
| { |
| return driver; |
| } |
| else |
| { |
| return CreateFreshDriver(); |
| } |
| } |
| |
| public IWebDriver CreateDriverInstance() |
| { |
| return driverFactory.CreateDriver(driverType); |
| } |
| |
| public IWebDriver CreateDriverInstance(DriverOptions options) |
| { |
| return driverFactory.CreateDriverWithOptions(driverType, options); |
| } |
| |
| public IWebDriver CreateFreshDriver() |
| { |
| CloseCurrentDriver(); |
| driver = CreateDriverInstance(); |
| return driver; |
| } |
| |
| public void CloseCurrentDriver() |
| { |
| if (driver != null) |
| { |
| driver.Quit(); |
| } |
| driver = null; |
| } |
| |
| protected void OnDriverStarting(object sender, DriverStartingEventArgs e) |
| { |
| if (this.DriverStarting != null) |
| { |
| this.DriverStarting(sender, e); |
| } |
| } |
| } |