From fa6b7b4be8e1865c30d6f6c0a57a53909ff3b540 Mon Sep 17 00:00:00 2001 From: RohitM-IN Date: Sat, 26 Aug 2023 19:21:30 +0530 Subject: [PATCH 1/4] Ratio Calculation fixed. Note- make sure that the key of the statictis always match with name of browser of status endpoint --- .../Configuration/config.json | 6 +-- .../DataContract/ConfigurationSettings.cs | 2 +- SeleniumManager.Core/SeleniumManager.cs | 40 ++++++++++++------- SeleniumManager.Core/Utils/RatioDictionary.cs | 37 ++++++++++------- 4 files changed, 51 insertions(+), 34 deletions(-) diff --git a/SeleniumManager.Core/Configuration/config.json b/SeleniumManager.Core/Configuration/config.json index ea6d195..b7ba208 100644 --- a/SeleniumManager.Core/Configuration/config.json +++ b/SeleniumManager.Core/Configuration/config.json @@ -3,9 +3,9 @@ "UserName": "", "Password": "", "statistics": { - "Chrome": 2, - "MicrosoftEdge": 1, - "Firefox": 1, + "chrome": 0.47, + "MicrosoftEdge": 0.38, + "firefox": 0.15, "Internet Explorer": 0 }, "endpoints": { diff --git a/SeleniumManager.Core/DataContract/ConfigurationSettings.cs b/SeleniumManager.Core/DataContract/ConfigurationSettings.cs index 22a6a17..6dc0478 100644 --- a/SeleniumManager.Core/DataContract/ConfigurationSettings.cs +++ b/SeleniumManager.Core/DataContract/ConfigurationSettings.cs @@ -25,7 +25,7 @@ public string GridHost _GridHost = value; } } - public Dictionary statistics { get; set; } + public Dictionary statistics { get; set; } public string UserName { get; set; } public string Password { get; set; } public Endpoints Endpoints { get; set; } diff --git a/SeleniumManager.Core/SeleniumManager.cs b/SeleniumManager.Core/SeleniumManager.cs index 56f01fd..3e4dd1f 100644 --- a/SeleniumManager.Core/SeleniumManager.cs +++ b/SeleniumManager.Core/SeleniumManager.cs @@ -356,31 +356,41 @@ private bool IsBrowserAvailable(string browserName) private async Task FindBestAvailableBrowser() { - var statistics = RatioDictionary.GetRatioDictionary(_configSettings.statistics, MaxSessions); - - foreach (var kvp in statistics.OrderByDescending(x => x.Value)) + try { await _availableStereotypesSemaphore.WaitAsync(); - var browserName = kvp.Key; - var maxInstances = kvp.Value; - ConcurrentStereotypes.TryGetValue(kvp.Key.ToLower(), out var concurrentInstances); - AvailableStereotypes.TryGetValue(kvp.Key.ToLower(), out var availableInstances); + var statistics = RatioDictionary.GetRatioDictionary(_configSettings.statistics, MaxSessions); - if (maxInstances >= concurrentInstances && !string.IsNullOrEmpty(browserName)) + foreach (var kvp in statistics.OrderByDescending(x => x.Value)) { + var browserName = kvp.Key; + var maxInstances = kvp.Value; + ConcurrentStereotypes.TryGetValue(kvp.Key, out var concurrentInstances); + AvailableStereotypes.TryGetValue(kvp.Key, out var availableInstances); - AdjustInstance(browserName.ToLower(), AdjustType.Create); + if (maxInstances > concurrentInstances && !string.IsNullOrEmpty(browserName)) + { - _availableStereotypesSemaphore.Release(); - return browserName.ToString(); + AdjustInstance(browserName, AdjustType.Create); + return browserName.ToString(); + } + + continue; } - _availableStereotypesSemaphore.Release(); - continue; + + // If no available browser is found, return the browser with the highest instances count + return statistics.OrderByDescending(x => x.Value).FirstOrDefault().Key ?? WebDriverType.Chrome.GetDescription(); } + catch (System.Exception) + { - // If no available browser is found, return the browser with the highest instances count - return statistics.OrderByDescending(x => x.Value).FirstOrDefault().Key ?? WebDriverType.Chrome.GetDescription(); + throw; + } + finally + { + _availableStereotypesSemaphore.Release(); + } } private void AdjustInstance(string key, AdjustType type) diff --git a/SeleniumManager.Core/Utils/RatioDictionary.cs b/SeleniumManager.Core/Utils/RatioDictionary.cs index 2ee71ab..24d5e10 100644 --- a/SeleniumManager.Core/Utils/RatioDictionary.cs +++ b/SeleniumManager.Core/Utils/RatioDictionary.cs @@ -2,28 +2,35 @@ { public class RatioDictionary { - public static Dictionary GetRatioDictionary(Dictionary dict, int maxNumber) + public static Dictionary GetRatioDictionary(Dictionary dict, int maxNumber) { + // Calculate the total sum of values in the input dictionary + double totalValue = dict.Values.Sum(); + + // Calculate a ratio factor based on the total number and sum of values + double ratioFactor = maxNumber / totalValue; + Dictionary share = new Dictionary(); - foreach (KeyValuePair item in dict) + int totalAllocated = 0; + + foreach (KeyValuePair item in dict) { - share[item.Key] = (int)(item.Value * maxNumber / sum(dict.Values)); + // Calculate the number of instances for the current browser type + int instances = (int)Math.Floor(item.Value * ratioFactor); + + // Store the instances count in the share dictionary + share[item.Key] = instances; + + // Keep track of the total allocated instances + totalAllocated += instances; } - int remainingValue = maxNumber - sum(share.Values); + int remainingValue = maxNumber - totalAllocated; + + // Distribute the remaining instances to the highest value if (remainingValue > 0) { - string highestValueKey = ""; - int highestValue = 0; - foreach (KeyValuePair item in share) - { - if (item.Value > highestValue) - { - highestValue = item.Value; - highestValueKey = item.Key; - } - } - + string highestValueKey = share.OrderByDescending(x => x.Value).First().Key; share[highestValueKey] += remainingValue; } From 6f5f94c53f276845e515efd4c12760497bb1bceb Mon Sep 17 00:00:00 2001 From: RohitM-IN Date: Sat, 26 Aug 2023 19:29:46 +0530 Subject: [PATCH 2/4] Update Configuration doc --- SeleniumManager.sln | 10 +++++++--- doc/Configuration.md | 12 ++++++------ 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/SeleniumManager.sln b/SeleniumManager.sln index 7407607..bd2fba0 100644 --- a/SeleniumManager.sln +++ b/SeleniumManager.sln @@ -3,16 +3,20 @@ Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 VisualStudioVersion = 17.5.33516.290 MinimumVisualStudioVersion = 10.0.40219.1 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SeleniumManager.Core", "SeleniumManager.Core\SeleniumManager.Core.csproj", "{B7FAAF9B-A860-4949-9605-A069E1B05BFB}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SeleniumManager.Core", "SeleniumManager.Core\SeleniumManager.Core.csproj", "{B7FAAF9B-A860-4949-9605-A069E1B05BFB}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{7D9E9DA4-B073-42C7-B197-E91494FB65CE}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig + doc\API_REFERENCE.md = doc\API_REFERENCE.md + doc\CODE_OF_CONDUCT.md = doc\CODE_OF_CONDUCT.md + doc\Configuration.md = doc\Configuration.md + doc\CONTRIBUTING.md = doc\CONTRIBUTING.md EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SeleniumManager.ConsoleApp", "SeleniumManager.ConsoleApp\SeleniumManager.ConsoleApp.csproj", "{BE559C8A-13DC-4C04-B959-8C968BF6A6DD}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SeleniumManager.ConsoleApp", "SeleniumManager.ConsoleApp\SeleniumManager.ConsoleApp.csproj", "{BE559C8A-13DC-4C04-B959-8C968BF6A6DD}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SeleniumManager.Tests", "SeleniumManager.Tests\SeleniumManager.Tests.csproj", "{04E33D40-4601-4D08-B0F8-A837CE94C350}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SeleniumManager.Tests", "SeleniumManager.Tests\SeleniumManager.Tests.csproj", "{04E33D40-4601-4D08-B0F8-A837CE94C350}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/doc/Configuration.md b/doc/Configuration.md index 61d3219..12c94cf 100644 --- a/doc/Configuration.md +++ b/doc/Configuration.md @@ -62,9 +62,9 @@ var configSettings = new ConfigurationSettings GridHost = "http://localhost:4444/wd/hub", statistics = new Dictionary { - { "chrome", 1 }, - { "firefox", 1 }, - { "MicrosoftEdge", 1 } + { "chrome", 0.5 }, + { "firefox", 0.2 }, + { "MicrosoftEdge", 0.3 } }, UserName = "your-username", Password = "your-password", @@ -92,9 +92,9 @@ var configSettings = new ConfigurationSettings "UserName": "", "Password": "", "statistics": { - "Chrome": 2, - "MicrosoftEdge": 1, - "Firefox": 1, + "Chrome": 0.47, + "MicrosoftEdge": 0.38, + "Firefox": 0.15, "Internet Explorer": 0 }, "endpoints": { From 362f489e360a07f4ba13b0a0e3573f47f65ad83f Mon Sep 17 00:00:00 2001 From: RohitM-IN Date: Sat, 26 Aug 2023 19:32:38 +0530 Subject: [PATCH 3/4] fix case sensitive browser names --- doc/Configuration.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/doc/Configuration.md b/doc/Configuration.md index 12c94cf..1a00e1a 100644 --- a/doc/Configuration.md +++ b/doc/Configuration.md @@ -45,7 +45,7 @@ The `ConfigurationSettings` class acts as a configuration hub for Selenium Manag - **Description**: A collection of endpoint URLs used by Selenium Manager to communicate with different parts of the Selenium Grid infrastructure. These endpoints include URLs for retrieving status, session details, and more. ### Options -- **Type**: Options +- **Type**: `Options` - **Description**: A collection of browser-specific options used to configure the behavior of WebDriver instances. This property holds sub-properties for each browser type (e.g., Chrome, Firefox) to allow you to set browser-specific options. ## Usage @@ -92,15 +92,16 @@ var configSettings = new ConfigurationSettings "UserName": "", "Password": "", "statistics": { - "Chrome": 0.47, + "chrome": 0.47, "MicrosoftEdge": 0.38, - "Firefox": 0.15, + "firefox": 0.15, "Internet Explorer": 0 }, "endpoints": { "status": "/status" } } + ``` Using above config file From 34673f866e68d42263d647bf1fdfa18acd336b16 Mon Sep 17 00:00:00 2001 From: RohitM-IN Date: Sun, 27 Aug 2023 13:12:17 +0530 Subject: [PATCH 4/4] Update to 1.2.1 --- SeleniumManager.Core/SeleniumManager.Core.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SeleniumManager.Core/SeleniumManager.Core.csproj b/SeleniumManager.Core/SeleniumManager.Core.csproj index 3107109..b8fe476 100644 --- a/SeleniumManager.Core/SeleniumManager.Core.csproj +++ b/SeleniumManager.Core/SeleniumManager.Core.csproj @@ -14,10 +14,10 @@ This include managing Queues, Parallel Tests, etc. MIT License True - 1.2.0.0 - 1.2.0.0 + 1.2.1.0 + 1.2.1.0 True - 1.2.0.0 + 1.2.1.0