public void CheckLocalAndRemoteBinaryFailsInvalidRemoteBuildId() { fileSystem.AddDirectory(searchPaths[0]); fileSystem.AddFile(localPaths[0], new MockFileData("")); binaryFileUtil.ReadBuildIdAsync(localPaths[0]).Returns(Task.FromResult(validBuildId)); binaryFileUtil.ReadBuildIdAsync(remoteTargetPath, target).Returns( Task.FromException <BuildId>(new InvalidBuildIdException("test"))); Exception ex = Assert.ThrowsAsync <PreflightBinaryCheckerException>(async() => await action.RecordAsync(checker.CheckLocalAndRemoteBinaryOnLaunchAsync( searchPaths, executable, target, remoteTargetPath, action))); Assert.IsInstanceOf <BinaryFileUtilException>(ex.InnerException); Assert.AreEqual(ErrorStrings.FailedToCheckRemoteBuildIdWithExplanation( ex.InnerException.Message), ex.Message); metrics.Received().RecordEvent( DeveloperEventType.Types.Type.VsiDebugPreflightBinaryCheck, Arg.Is <DeveloperLogEvent>(m => m.StatusCode == DeveloperEventStatus.Types.Code.InvalidConfiguration && m.DebugPreflightCheckData.CheckType == DebugPreflightCheckData.Types.CheckType.RunAndAttach && m.DebugPreflightCheckData.RemoteBuildIdCheckResult == DebugPreflightCheckData.Types.RemoteBuildIdCheckResult .InvalidRemoteBuildId)); }
public void CheckRemoteBinaryFailsToRunRemoteCommand() { binaryFileUtil.ReadBuildIdAsync(remoteTargetPath, target).Returns( Task.FromException <BuildId>(new BinaryFileUtilException("test", new ProcessException("inner")))); Exception ex = Assert.ThrowsAsync <PreflightBinaryCheckerException>(async() => await action.RecordAsync(checker.CheckRemoteBinaryOnAttachAsync(remoteTargetPid, target, action))); Assert.IsInstanceOf <BinaryFileUtilException>(ex.InnerException); Assert.AreEqual(ErrorStrings.FailedToCheckRemoteBuildIdWithExplanation( ex.InnerException.Message), ex.Message); metrics.Received().RecordEvent( DeveloperEventType.Types.Type.VsiDebugPreflightBinaryCheck, Arg.Is <DeveloperLogEvent>(m => m.StatusCode == DeveloperEventStatus.Types.Code.ExternalToolUnavailable && m.DebugPreflightCheckData.CheckType == DebugPreflightCheckData.Types.CheckType.AttachOnly && m.DebugPreflightCheckData.RemoteBuildIdCheckResult == DebugPreflightCheckData.Types.RemoteBuildIdCheckResult .RemoteCommandError)); }
/// <summary> /// Check that the specified remote process's binary has a valid build id. Log messages and /// record metrics to indicate the result of the checks. /// </summary> /// <param name="pid">Process ID of the remote process that we will check</param> /// <param name="target">The machine that should have a valid remote binary</param> public async Task CheckRemoteBinaryOnAttachAsync(uint pid, SshTarget target, IAction action) { var remoteTargetPath = string.Format(PID_EXE_PATH_TEMPLATE, pid); try { var dataRecorder = new DataRecorder(action, DebugPreflightCheckData.Types.CheckType.AttachOnly); BuildId remoteBuildId; try { remoteBuildId = await binaryFileUtil.ReadBuildIdAsync(remoteTargetPath, target); } catch (BinaryFileUtilException e) when(dataRecorder.RemoteBuildIdError(e)) { Debug.Fail("Exception should never be caught"); throw; } // Log the remote Build ID for debugging purposes. dataRecorder.ValidRemoveBuildId(); Trace.WriteLine("Remote build ID: " + remoteBuildId.ToString()); } catch (BinaryFileUtilException e) { Trace.WriteLine($"Failed to read build ID for '{remoteTargetPath}' " + $"on '{target.GetString()}': " + e.ToString()); throw new PreflightBinaryCheckerException( ErrorStrings.FailedToCheckRemoteBuildIdWithExplanation(e.Message), e); } }
/// <summary> /// Check that the remote binary for the given executable exists and has a valid build id. /// Look for a local copy of the binary based on the name and build id. Log messages and /// record metrics to indicate the result of the checks. /// </summary> /// <remarks> /// It is assumed the remote binary is at YetiConstants.RemoteDeployPath. /// </remarks> /// <param name="libPaths">LLDB search paths to check for local binaries</param> /// <param name="executable">Name of the binary to look for locally and remotely</param> /// <param name="target">The machine that should have a valid remote binary</param> public async Task CheckLocalAndRemoteBinaryOnLaunchAsync( IEnumerable <string> libPaths, string executable, SshTarget target, string remoteTargetPath, IAction action) { // Check that the remote binary has a build id and try to match it against // the local candidates to find the matching local binary. IEnumerable <string> localCandidatePaths = new List <string>(); try { var dataRecorder = new DataRecorder(action, DebugPreflightCheckData.Types.CheckType.RunAndAttach); // Get the remote build id and only continue if this step succeeds. BuildId remoteBuildId; try { remoteBuildId = await binaryFileUtil.ReadBuildIdAsync(remoteTargetPath, target); } catch (BinaryFileUtilException e) when(dataRecorder.RemoteBuildIdError(e)) { Debug.Fail("Exception should never be caught"); throw; } // Log the remote Build ID for debugging purposes. dataRecorder.ValidRemoveBuildId(); Trace.WriteLine("Remote build ID: " + remoteBuildId.ToString()); // Make sure there is a local binary with the same name. localCandidatePaths = FindExecutableCandidates(libPaths, executable); if (!localCandidatePaths.Any()) { dataRecorder.LocalBinaryCheckResult( DebugPreflightCheckData.Types.LocalBinarySearchResult.NoCandidates); throw new NoLocalCandidatesException(); } // Check local candidates to find one matching the remote build id. // Ignore local candidates that are missing a build id. if (await HasMatchingBuildIdAsync( localCandidatePaths, executable, remoteTargetPath, remoteBuildId)) { dataRecorder.LocalBinaryCheckResult( DebugPreflightCheckData.Types.LocalBinarySearchResult.BinaryMatch); } else { dataRecorder.LocalBinaryCheckResult( DebugPreflightCheckData.Types.LocalBinarySearchResult.BinaryMismatch); throw new NoMatchingLocalCandidatesException(); } } catch (BinaryFileUtilException e) { Trace.WriteLine($"Failed to read build ID for '{remoteTargetPath}' " + $"on '{target.GetString()}': " + e.ToString()); throw new PreflightBinaryCheckerException( ErrorStrings.FailedToCheckRemoteBuildIdWithExplanation(e.Message), e); } catch (NoLocalCandidatesException e) { Trace.WriteLine($"Unable to find executable '{executable}' on LLDB search paths."); throw new PreflightBinaryCheckerException( ErrorStrings.UnableToFindExecutable(executable), ErrorStrings.ExecutableCheckDetails(libPaths), e); } catch (NoMatchingLocalCandidatesException e) { Trace.WriteLine( $"No local copy of '{executable}' matched the build ID of the remote binary"); throw new PreflightBinaryCheckerException( ErrorStrings.UnableToFindExecutableMatchingRemoteBinary(executable, remoteTargetPath), ErrorStrings.BuildIdCheckDetails(localCandidatePaths, libPaths), e); } }