// runWithCustomInteractor executes the problem solution with the given custom interactor.
runWithCustomInteractor executes the problem solution with the given custom interactor.
// runWithCustomInteractor executes the problem solution with the given custom interactor .
func (e *Executor) runWithCustomInteractor(testCase *testCaseFiles) error {
	var err error
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	interactor := e.InteractorProgramService.GetExecutionCommand(ctx, e.filePathInteractorSource, e.filePathInteractorBinary)
	interactor, err = e.InteractorCage.Encage(interactor)
	if err != nil {
		return fmt.Errorf("error encaging interactor command: %w", err)
	}
	solution := e.SolutionProgramService.GetExecutionCommand(ctx, e.filePathSolutionSource, e.filePathSolutionBinary)
	solution, err = e.SolutionCage.Encage(solution)
	if err != nil {
		return fmt.Errorf("error encaging solution command: %w", err)
	}
	output, err := e.FileService.CreateFile(testCase.output)
	if err != nil {
		return fmt.Errorf("error creating output file for test case execution: %w", err)
	}
	output.Close()
	interactorInput, err := interactor.StdinPipe()
	if err != nil {
		return fmt.Errorf("error creating pipe for interactor input: %w", err)
	}
	defer interactorInput.Close()
	interactorOutput, err := interactor.StdoutPipe()
	if err != nil {
		return fmt.Errorf("error creating pipe for interactor output: %w", err)
	}
	defer interactorOutput.Close()
	solutionInput, err := solution.StdinPipe()
	if err != nil {
		return fmt.Errorf("error creating pipe for solution input: %w", err)
	}
	defer solutionInput.Close()
	solutionOutput, err := solution.StdoutPipe()
	if err != nil {
		return fmt.Errorf("error creating pipe for solution output: %w", err)
	}
	defer solutionOutput.Close()
	if err := interactor.Start(); err != nil {
		return fmt.Errorf("error starting interactor process: %w", err)
	}
	defer func() { _ = interactor.Wait() }()
	if err := solution.Start(); err != nil {
		return fmt.Errorf("error starting solution process: %w", err)
	}
	defer func() { _ = solution.Wait() }()
	_, err = interactorInput.Write([]byte(testCase.input + "\n" + testCase.output + "\n"))
	if err != nil {
		return fmt.Errorf("error writing input and output file paths to interactor input: %w", err)
	}
	pipeErrors := make(chan error, 2)
	go func() {
		if _, err := io.Copy(solutionInput, interactorOutput); err != nil {
			pipeErrors <- fmt.Errorf("error copying interactor output pipe to solution input pipe: %w", err)
		} else {
			pipeErrors <- solutionInput.Close() 
		}
	}()
	go func() {
		if _, err := io.Copy(interactorInput, solutionOutput); err != nil {
			pipeErrors <- fmt.Errorf("error copying solution output pipe to interactor input pipe: %w", err)
		} else {
			pipeErrors <- nil
		}
	}()
	for i := 0; i < 2; i++ {
		pipeError := <-pipeErrors
		if pipeError != nil {
			return pipeError
		}
	}
	return nil
}
func ( e * Executor ) runWithCustomInteractor ( testCase * testCaseFiles ) error { var err error ctx , cancel := context . WithCancel ( context . Background ( ) ) defer cancel ( ) interactor := e . InteractorProgramService . GetExecutionCommand ( ctx , e . filePathInteractorSource , e . filePathInteractorBinary ) interactor , err = e . InteractorCage . Encage ( interactor ) if err != nil { return fmt . Errorf ( " " , err ) } solution := e . SolutionProgramService . GetExecutionCommand ( ctx , e . filePathSolutionSource , e . filePathSolutionBinary ) solution , err = e . SolutionCage . Encage ( solution ) if err != nil { return fmt . Errorf ( " " , err ) } output , err := e . FileService . CreateFile ( testCase . output ) if err != nil { return fmt . Errorf ( " " , err ) } output . Close ( ) interactorInput , err := interactor . StdinPipe ( ) if err != nil { return fmt . Errorf ( " " , err ) } defer interactorInput . Close ( ) interactorOutput , err := interactor . StdoutPipe ( ) if err != nil { return fmt . Errorf ( " " , err ) } defer interactorOutput . Close ( ) solutionInput , err := solution . StdinPipe ( ) if err != nil { return fmt . Errorf ( " " , err ) } defer solutionInput . Close ( ) solutionOutput , err := solution . StdoutPipe ( ) if err != nil { return fmt . Errorf ( " " , err ) } defer solutionOutput . Close ( ) if err := interactor . Start ( ) ; err != nil { return fmt . Errorf ( " " , err ) } defer func ( ) { _ = interactor . Wait ( ) } ( ) if err := solution . Start ( ) ; err != nil { return fmt . Errorf ( " " , err ) } defer func ( ) { _ = solution . Wait ( ) } ( ) _ , err = interactorInput . Write ( [ ] byte ( testCase . input + " \n " + testCase . output + " \n " ) ) if err != nil { return fmt . Errorf ( " " , err ) } pipeErrors := make ( chan error , 2 ) go func ( ) { if _ , err := io . Copy ( solutionInput , interactorOutput ) ; err != nil { pipeErrors <- fmt . Errorf ( " " , err ) } else { pipeErrors <- solutionInput . Close ( ) } } ( ) go func ( ) { if _ , err := io . Copy ( interactorInput , solutionOutput ) ; err != nil { pipeErrors <- fmt . Errorf ( " " , err ) } else { pipeErrors <- nil } } ( ) for i := 0 ; i < 2 ; i ++ { pipeError := <- pipeErrors if pipeError != nil { return pipeError } } return nil }
runWithCustomInteractor executes the problem solution with the given custom interactor.
runWithCustomInteractor executes the problem solution with the given custom interactor .
// tells solution process to exit