//The logic is: //1. For both logcats: Make copy from the "source" logcat. //2. For detailedLogcat: nothing else needs to be done. This program does not use it (it's kept here only for end-users: they may need full logs if the test fails). //3. For briefLogcat: Just ReadLine(); through logs until it reaches offset //3. Read logs after the offset and place them into Logcat struct //4. Return Logcat public Logcat UpdateLogcat(Logcat logcat, int offset) { if (offset < 0) { throw new ArgumentOutOfRangeException("Trying to update Logcat with incorrect offset: " + offset); } File.Copy(Settings.briefLogcatFilePath, logcat.briefLogcatPath, true); File.Copy(Settings.detailedLogcatFilePath, logcat.detailedLogcatPath, true); StreamReader file = new StreamReader(logcat.briefLogcatPath); int linesToSkip = offset; while (linesToSkip > 0) { file.ReadLine(); linesToSkip--; } while (!file.EndOfStream) { while (logcat.logs.Count <= offset) { //if there are less elements than "offset" (which is the index we will be inserting a value at), add an element. logcat.logs.Add(""); } logcat.logs[offset] = file.ReadLine(); offset++; } file.Close(); return(logcat); }
//Begin logcat starts two processes collecting two logcats. Both of them need to be maintained. //One of them is "detailedLogcat" which is collecting all info related to this PID and it will be helpful for debugging //The second one is "briefLogcat" which is used by this program to determine conditions and actions of TestSteps. //The logic is: // 1. Check if files exist - if yes, delete them (they may be the result of the previous run) // 2. Clear device's logcat // 3. Run new process for both logcats // 4. Set the path to which logcats will be copied and read // 5. Return logcat //There is a reason .bat is used here. Cmd.exe crashes and stops logging after a few minutes for unknown reasons. public Logcat BeginLogcat(string packagename) { //first, clean up the old files Helpers.DeleteFileIfExists(Settings.briefLogcatFilePath); Helpers.DeleteFileIfExists(Settings.detailedLogcatFilePath); //second, create new ones Logcat logcat = new Logcat(); logcat.logs = new List <string>(); Directory.CreateDirectory(Settings.logcatContainerDirectory); //clear device's logs CommandLineExecutor.ExecuteCommand("adb logcat -c"); //run .bats that will start logcat CommandLineExecutor.ExecuteScript(ADBScriptedFunctionsSettings.GetFunctionsFilePath(ADBScriptedFunctionsSettings.EScriptedFunction.startBriefLogcat), String.Empty, String.Empty); CommandLineExecutor.ExecuteScript(ADBScriptedFunctionsSettings.GetFunctionsFilePath(ADBScriptedFunctionsSettings.EScriptedFunction.startDetailedLogcat), String.Empty, String.Empty); logcat.detailedLogcatPath = Settings.GetPathForCopy(Settings.briefLogcatFilePath); logcat.briefLogcatPath = Settings.GetPathForCopy(Settings.detailedLogcatFilePath); return(logcat); }
//TODO public void EndLogcat(Logcat logcat) { throw new NotImplementedException("Ending Logcat is not implemented yet."); }
void ExecuteTestSteps(List <TestStep> testStepsPlan) { int logcatOffset = 0; //begin adb logcat logcat = device.logcatOperator.BeginLogcat(packagename); //now execute every step int testStepIndex = 0; while (testStepIndex < testStepsPlan.Count) { TestStep currentStep = testStepsPlan[testStepIndex]; bool isStepSuccess = false; bool isConditionPresent = false; bool isConfirmationPresent = false; int alreadyWaitedFor = 0; Thread.Sleep(1500); //TODO: Individual delay for each step ExecuteAction(currentStep); while (!isStepSuccess) { logcat = device.logcatOperator.UpdateLogcat(logcat, logcatOffset); //Read new logs and check every line //TODO: Blacklist. Check every line for error or exception while (logcatOffset < logcat.logs.Count) { if (!isConditionPresent) { isConditionPresent = IsTargetPresent(logcat.logs[logcatOffset], currentStep.conditionLog); if (isConditionPresent) { Thread.Sleep(currentStep.waitTime); } } if (isConditionPresent && !isConfirmationPresent) { isConfirmationPresent = IsTargetPresent(logcat.logs[logcatOffset], currentStep.confirmationLog); } if (isConditionPresent && isConfirmationPresent) { isStepSuccess = true; break; } OnLogRead(logcat.logs[logcatOffset]); logcatOffset++; } //If !isStepSuccess is checked later on because there is a possibility to retry if (isStepSuccess) { OnStepSucceeded(currentStep.id); testStepIndex++; break; } //If no confirmation log was found, wait 500 ms before updating logcat again Thread.Sleep(500); alreadyWaitedFor += 500; if (alreadyWaitedFor > currentStep.terminationTime) //unless it times out { break; } } if (!isStepSuccess) { switch (currentStep.actionIfFailed) { case TestDatabase.TestAction.Back: device.deviceModel.InputBack(); testStepIndex++; break; case TestDatabase.TestAction.BackAndRetry: device.deviceModel.InputBack(); break; case TestDatabase.TestAction.Next: OnStepFailed(currentStep.id); testStepIndex++; break; case TestDatabase.TestAction.Retry: break; case TestDatabase.TestAction.Stop: OnStepFailed(currentStep.id); OnTestEnded(TestResultEventArgs.ResultType.StepFailed); testStepIndex = testStepsPlan.Count; break; default: throw new ArgumentException("No behaviour found for this type of action: " + Enum.GetName(typeof(TestDatabase.TestAction), currentStep.actionIfFailed)); } //It checks if the device is disconnected to be sure it was not the cause of the failure. if (!device.deviceModel.IsDeviceReady()) { OnTestEnded(TestResultEventArgs.ResultType.DeviceDisconnected); } } } }