/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed 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. */ using System; using System.Linq; using NUnit.Framework; using QuantConnect.API; using QuantConnect.Configuration; namespace QuantConnect.Tests.API { [TestFixture, Ignore("These tests require an account, token, and organization ID")] /// /// Test class for all nodes/ endpoints: /// create, read, update, delete, stop /// public class NodeTests { private int _testAccount = 1; private string _testToken = "ec87b337ac970da4cbea648f24f1c851"; private string _testOrganization = "enter Org ID here"; private string _dataFolder = Config.Get("data-folder"); private Api.Api _api; /// /// Setup for this text fixture, will create API connection. /// [SetUp] public void Setup() { _api = new Api.Api(); _api.Initialize(_testAccount, _testToken, _dataFolder); } /// /// Create a new backtest node with 2 CPU cores and 8GB of RAM check for successful /// creation in API response. /// [Test] public void CreateNewNode() { var sku = new SKU(2, 8, NodeType.Backtest); var nodeName = $"{DateTime.UtcNow.Minute}:{DateTime.UtcNow.Second}-Pinocho"; var newNode = _api.CreateNode(nodeName, _testOrganization, sku); Assert.IsTrue(newNode.Success); } /// /// Read all the nodes from the organization and check for a successful reply /// from the API. /// [Test] public void ReadNode() { var result = _api.ReadNodes(_testOrganization); Assert.IsTrue(result.Success); } /// /// Create, Read, Update, and Delete a node! /// /// Number of cores for the node /// Amount of RAM in GB for the node /// Target environment for the node [TestCase(2, 8, NodeType.Backtest)] [TestCase(0, 0, NodeType.Live)] [TestCase(8, 16, NodeType.Research)] public void CRUDNodes(int cores, int memory, NodeType target) { var sku = new SKU(cores, memory, target); var nodeName = $"{DateTime.UtcNow.Minute}:{DateTime.UtcNow.Second}-Pinocho"; var nodeName2 = $"{DateTime.UtcNow.Minute}:{DateTime.UtcNow.Second}-Monstro"; // First create a new node var createdNode = _api.CreateNode(nodeName, _testOrganization, sku); //Check for the nodes existance using the helper function var foundNode = FindNodeByName(nodeName); Assert.IsNotNull(foundNode); //Update that node with a new name var updateNodeRequest = _api.UpdateNode(foundNode.Id, nodeName2, _testOrganization); Assert.IsTrue(updateNodeRequest.Success); //Read again and check for the new name (nodeName2) foundNode = FindNodeByName(nodeName2); Assert.IsNotNull(foundNode); //Delete this node var deleteNodeRequest = _api.DeleteNode(foundNode.Id, _testOrganization); Assert.IsTrue(deleteNodeRequest.Success); //Read again and ensure the node does not exist. foundNode = FindNodeByName(nodeName2); Assert.IsNull(foundNode); } /// /// Helper function for finding a node by name, used by tests that are looking /// for a certain node. /// With some small adjustments could be moved to an api function. /// /// Name of the node /// The Node if found, null if not public Node FindNodeByName(string name) { Node result = null; var readNodeRequest = _api.ReadNodes(_testOrganization); var allNodes = readNodeRequest.BacktestNodes.Concat(readNodeRequest.LiveNodes).Concat(readNodeRequest.ResearchNodes); foreach (var Node in allNodes) { if (Node.Name == name) { result = Node; break; } } return result; } /// /// Test to ensure SKUs are generated correctly for a given Node configuration /// /// Number of cores /// Size of memory /// Target node environment /// Expected Result [TestCase(0, 0, NodeType.Live, "L-MICRO")] [TestCase(1, 1, NodeType.Live, "L1-1")] [TestCase(1, 2, NodeType.Live, "L1-2")] [TestCase(1, 4, NodeType.Live, "L1-4")] [TestCase(2, 8, NodeType.Backtest, "B2-8")] [TestCase(4, 12, NodeType.Backtest, "B4-12")] [TestCase(1, 4, NodeType.Research, "R1-4")] [TestCase(2, 8, NodeType.Research, "R2-8")] [TestCase(4, 12, NodeType.Research, "R4-12")] [TestCase(8, 16, NodeType.Research, "R8-16")] public void SkuIsGeneratedCorrectly(int cores, int memory, NodeType target, string expectedResult) { var SKU = new SKU(cores, memory, target); Assert.IsTrue(SKU.ToString() == expectedResult); } /// /// Read in the list of nodes from an organizations and stop any /// that are currently busy /// [Test] public void ReadAndStop() { // Then read the nodes from the org var readNodeRequest = _api.ReadNodes(_testOrganization); Assert.IsTrue(readNodeRequest.Success); //Iterate through all nodes and stop them if they are running var allNodes = readNodeRequest.BacktestNodes.Concat(readNodeRequest.LiveNodes).Concat(readNodeRequest.ResearchNodes); foreach (var Node in allNodes) { // If it is busy then stop it if (Node.Busy) { var stopNodeRequest = _api.StopNode(Node.Id, _testOrganization); Assert.IsTrue(stopNodeRequest.Success); } } } } }