public void WhenPathIsNull_ShouldReturnNull( ) { var fixture = new Fixture( ); var result = LinuxPath.GetFileName(null); Assert.Null(result); }
public void SyncServicePullFileTest() { Device device = GetFirstDevice(); FileListingService fileListingService = new FileListingService(device); using (ISyncService sync = device.SyncService) { String rfile = "/sdcard/bootanimations/bootanimation-cm.zip"; FileEntry rentry = fileListingService.FindFileEntry(rfile); String lpath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); String lfile = Path.Combine(lpath, LinuxPath.GetFileName(rfile)); FileInfo lfi = new FileInfo(lfile); SyncResult result = sync.PullFile(rfile, lfile, new FileSyncProgressMonitor()); Assert.IsTrue(lfi.Exists); Assert.IsTrue(ErrorCodeHelper.RESULT_OK == result.Code, ErrorCodeHelper.ErrorCodeToString(result.Code)); lfi.Delete(); result = sync.PullFile(rentry, lfile, new FileSyncProgressMonitor()); Assert.IsTrue(lfi.Exists); Assert.IsTrue(ErrorCodeHelper.RESULT_OK == result.Code, ErrorCodeHelper.ErrorCodeToString(result.Code)); lfi.Delete(); } }
public void WhenPathIsDirectory_ShouldReturnEmpty( ) { var fixture = new Fixture( ); var p1 = fixture.Create("/path1-"); var p2 = "{0}/".With(fixture.Create("path2-")); var p = LinuxPath.Combine(p1, p2); var result = LinuxPath.GetFileName(p); Assert.Equal(string.Empty, result); }
public void WhenPathIsFileWithoutExtension_ShouldReturnFileWithoutExtension( ) { var fixture = new Fixture( ); var p1 = fixture.Create("/path1-"); var p2 = "{0}/".With(fixture.Create("path2-")); var f = "{0}".With(fixture.Create("file-")); var p = LinuxPath.Combine(p1, p2, f); var result = LinuxPath.GetFileName(p); Assert.Equal(f, result); }
/// <summary> /// Initializes a new instance of the <see cref="FileEntry"/> class. /// </summary> /// <param name="device">The device.</param> /// <param name="path">The path.</param> internal FileEntry(Device device, string path) { this.FetchTime = 0; this.Parent = null; bool isDir = path.EndsWith(new string(LinuxPath.DirectorySeparatorChar, 1)); this.Name = isDir ? LinuxPath.GetDirectoryName(path) : LinuxPath.GetFileName(path); this.IsRoot = path.Length == 1 && path[0] == LinuxPath.DirectorySeparatorChar; this.Type = isDir ? FileListingService.FileTypes.Directory : FileListingService.FileTypes.File; this.Size = 0; this.Children = new List <FileEntry>(); this.Exists = false; this.Device = device; }
public void GetFileNameTest() { String result = LinuxPath.GetFileName("/system/busybox"); Assert.AreEqual <string>("busybox", result); result = LinuxPath.GetFileName("/"); Assert.AreEqual <string>("", result); result = LinuxPath.GetFileName("/system/xbin/"); Assert.AreEqual <string>("", result); result = LinuxPath.GetFileName("/system/xbin/file.ext"); Assert.AreEqual <string>("file.ext", result); }
public void WhenPathContainsInvalidCharacter_ShouldThrowArgumentException( ) { var fixture = new Fixture( ); int errorCount = 0; for (var x = 0; x < LinuxPathConsts.InvalidPathChars.Length; ++x) { try { string result = LinuxPath.GetFileName("/some/path/{0}-{1}.ext".With(LinuxPathConsts.InvalidPathChars[x], fixture.Create("file-"))); } catch (ArgumentException) { errorCount++; } } Assert.Equal(LinuxPathConsts.InvalidPathChars.Length, errorCount); }
/// <summary> /// <para> /// Handles the cleanup of tasks targeting the current cluster node: /// </para> /// <list type="bullet"> /// <item> /// Tasks whose <see cref="V1NeonNodeTask.TaskStatus.AgentId"/> doesn't match /// the ID for the current agent will be marked as <see cref="V1NeonNodeTask.Phase.Orphaned"/> /// and the finish time will be set to now. This sets the task up for eventual /// deletion. /// </item> /// <item> /// Tasks with a finish time that is older than <see cref="V1NeonNodeTask.TaskSpec.RetentionTime"/> /// will be removed. /// </item> /// <item> /// Scheduled tasks that missed their scheduling window will be marked as TARDY and /// will be retained for a while before being deleted. /// </item> /// </list> /// </summary> /// <returns>The tracking <see cref="Task"/>.</returns> private async Task CleanupTasksAsync() { var utcNow = DateTime.UtcNow; var nodeTasks = (await k8s.ListClusterCustomObjectAsync <V1NeonNodeTask>()).Items .Where(tasks => NodeTaskFilter(tasks)) .ToArray(); foreach (var nodeTask in nodeTasks) { var taskName = nodeTask.Name(); //------------------------------------------------------------- // Remove invalid tasks. try { nodeTask.Validate(); } catch (Exception e) { log.LogWarn($"Invalid NodeTask: [{taskName}]", e); log.LogWarn($"Deleting invalid NodeTask: [{taskName}]"); await k8s.DeleteClusterCustomObjectAsync(nodeTask); continue; } if (nodeTask.Status.Phase == V1NeonNodeTask.Phase.Running) { //--------------------------------------------------------- // Detect and kill orphaned tasks. if (nodeTask.Status.AgentId != Node.AgentId) { log.LogWarn($"Detected orphaned [nodetask={taskName}]: task [agentID={nodeTask.Status.AgentId}] does not match operator [agentID={Node.AgentId}]"); // Update the node task status to: ORPHANED var patch = OperatorHelper.CreatePatch <V1NeonNodeTask>(); patch.Replace(path => path.Status.Phase, V1NeonNodeTask.Phase.Orphaned); patch.Replace(path => path.Status.FinishTimestamp, utcNow); patch.Replace(path => path.Status.ExitCode, -1); await k8s.PatchClusterCustomObjectStatusAsync <V1NeonNodeTask>(OperatorHelper.ToV1Patch <V1NeonNodeTask>(patch), nodeTask.Name()); await KillTaskAsync(nodeTask); continue; } //--------------------------------------------------------- // Kill tasks that have been running for too long. if (nodeTask.Status.Phase == V1NeonNodeTask.Phase.Running && utcNow - nodeTask.Status.StartTimestamp >= TimeSpan.FromSeconds(nodeTask.Spec.TimeoutSeconds)) { log.LogWarn($"Execution timeout [nodetask={taskName}]: execution time exceeds [{nodeTask.Spec.TimeoutSeconds}]."); await KillTaskAsync(nodeTask); // Update the node task status to: TIMEOUT var patch = OperatorHelper.CreatePatch <V1NeonNodeTask>(); patch.Replace(path => path.Status.Phase, V1NeonNodeTask.Phase.Timeout); patch.Replace(path => path.Status.FinishTimestamp, utcNow); patch.Replace(path => path.Status.RuntimeSeconds, (int)Math.Ceiling((utcNow - nodeTask.Status.StartTimestamp.Value).TotalSeconds)); patch.Replace(path => path.Status.ExitCode, -1); await k8s.PatchClusterCustomObjectStatusAsync <V1NeonNodeTask>(OperatorHelper.ToV1Patch <V1NeonNodeTask>(patch), nodeTask.Name()); continue; } //--------------------------------------------------------- // Detect that missed their scheduling window and mark them as tardy if (nodeTask.Status.Phase == V1NeonNodeTask.Phase.Pending && nodeTask.Spec.StartBeforeTimestamp.HasValue && nodeTask.Spec.StartBeforeTimestamp <= utcNow) { log.LogWarn($"Detected tardy [nodetask={taskName}]: task execution didn't start before [{nodeTask.Spec.StartBeforeTimestamp}]."); // Update the node task status to: TARDY var patch = OperatorHelper.CreatePatch <V1NeonNodeTask>(); patch.Replace(path => path.Status.Phase, V1NeonNodeTask.Phase.Tardy); patch.Replace(path => path.Status.FinishTimestamp, utcNow); patch.Replace(path => path.Status.ExitCode, -1); await k8s.PatchClusterCustomObjectStatusAsync <V1NeonNodeTask>(OperatorHelper.ToV1Patch <V1NeonNodeTask>(patch), nodeTask.Name()); continue; } } } //----------------------------------------------------------------- // Remove tasks that have been retained long enough. foreach (var nodeTask in nodeTasks .Where(task => task.Status.Phase != V1NeonNodeTask.Phase.New && task.Status.Phase != V1NeonNodeTask.Phase.Running) .Where(task => (utcNow - task.Status.FinishTimestamp) >= TimeSpan.FromSeconds(task.Spec.RetentionSeconds))) { log.LogWarn($"[nodetask={nodeTask.Name()}]: has been retained for [{nodeTask.Spec.RetentionSeconds}] (deleting now)."); await k8s.DeleteClusterCustomObjectAsync(nodeTask); } //----------------------------------------------------------------- // Remove any script folders whose node task no longer exists. if (NeonHelper.IsLinux) { var nodeTaskExecuteIds = new HashSet <string>(); foreach (var nodeTask in nodeTasks.Where(task => !string.IsNullOrEmpty(task.Status.RunId))) { nodeTaskExecuteIds.Add(nodeTask.Status.RunId); } foreach (var scriptFolderPath in Directory.GetDirectories(hostNeonTasksFolder, "*", SearchOption.TopDirectoryOnly)) { var scriptFolderName = LinuxPath.GetFileName(scriptFolderPath); if (!nodeTaskExecuteIds.Contains(scriptFolderName)) { log.LogWarn($"Removing node task host script folder: {scriptFolderName}"); NeonHelper.DeleteFolder(scriptFolderPath); } } } }
public void GetFileName() { Assert.Equal("three.txt", LinuxPath.GetFileName("\\one\\two\\three.txt")); Assert.Equal("three.txt", LinuxPath.GetFileName("/one/two/three.txt")); }