Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fg & bg built-ins #339

Merged
merged 14 commits into from
Jan 9, 2024
Merged

Fg & bg built-ins #339

merged 14 commits into from
Jan 9, 2024

Conversation

magicant
Copy link
Owner

@magicant magicant commented Jan 8, 2024

Summary by CodeRabbit

  • New Features

    • Introduced bg built-in command for resuming suspended jobs in the background.
    • Introduced fg built-in command for resuming suspended jobs in the foreground.
  • Enhancements

    • Improved job status handling with expected_status field and methods.
    • Enhanced job reporting with new number method in Report struct.
  • Tests

    • Added new tests for bg and fg built-in commands.
    • Included comprehensive test suites bg-p.sh and fg-p.sh for POSIX compliance.
  • Bug Fixes

    • Fixed signal handling in send_signal_to_processes function to check results before raising signals.

@magicant magicant added the enhancement New feature or request label Jan 8, 2024
@magicant magicant added this to the POSIX 2018 scripting milestone Jan 8, 2024
@magicant magicant self-assigned this Jan 8, 2024
Copy link

coderabbitai bot commented Jan 8, 2024

Walkthrough

The yash shell has been updated to include bg and fg built-in commands, enhancing job control by allowing jobs to be continued in the background or foreground. The update includes error handling, status management, and job control checks, as well as new tests to ensure compliance with POSIX standards.

Changes

Files Summary
yash-builtin/src/bg.rs
yash-builtin/src/fg.rs
Implementation of bg and fg built-in commands for resuming suspended jobs in the background and foreground respectively, along with error handling and status updates.
yash-builtin/src/lib.rs Addition of bg and fg modules to the public API and updates to the tests module.
yash-env/src/job.rs
yash-env/src/job/fmt.rs
Modification to include an expected_status field in Job and updates to job formatting and status handling.
yash-env/src/system/virtual.rs Changes to signal sending logic and the addition of a new test for signal handling.
yash-semantics/src/command/item.rs
yash/tests/scripted_test.rs
Addition of job control checks in execute_async and new test functions for bg and fg built-ins.
yash/tests/scripted_test/bg-p.sh
yash/tests/scripted_test/fg-p.sh
Introduction of test suites for bg and fg built-in commands to ensure POSIX compliance.

🐇✨
A rabbit hopped through the code, with care,
Adding bg and fg with flair.
Jobs wake up or come to the fore,
Yash shell's better than before! 🎉
🐇✨

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share

Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit-tests for this file.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit tests for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository from git and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit tests.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger a review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • The JSON schema for the configuration file is available here.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json

CodeRabbit Discord Community

Join our Discord Community to get help, request features, and share feedback.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 4

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 460412e and 786318e.
Files selected for processing (10)
  • yash-builtin/src/bg.rs (1 hunks)
  • yash-builtin/src/fg.rs (1 hunks)
  • yash-builtin/src/lib.rs (6 hunks)
  • yash-env/src/job.rs (7 hunks)
  • yash-env/src/job/fmt.rs (1 hunks)
  • yash-env/src/system/virtual.rs (2 hunks)
  • yash-semantics/src/command/item.rs (3 hunks)
  • yash/tests/scripted_test.rs (2 hunks)
  • yash/tests/scripted_test/bg-p.sh (1 hunks)
  • yash/tests/scripted_test/fg-p.sh (1 hunks)
Additional comments: 33
yash/tests/scripted_test/fg-p.sh (1)
  • 18-77: The error handling tests in fg-p.sh are comprehensive, covering scenarios where job control is disabled and when non-existent jobs are specified. These tests are crucial for ensuring the robustness of the fg built-in command in error scenarios.
yash/tests/scripted_test/bg-p.sh (1)
  • 17-102: The error handling tests in bg-p.sh are comprehensive, covering scenarios where job control is disabled and when non-existent jobs are specified. These tests are crucial for ensuring the robustness of the bg built-in command in error scenarios.
yash/tests/scripted_test.rs (2)
  • 96-99: The addition of the bg_builtin test function in scripted_test.rs is correctly implemented. It uses run_with_pty to execute the bg-p.sh script, which is appropriate for testing job control built-ins that may require a pseudo-terminal.

  • 151-154: The addition of the fg_builtin test function in scripted_test.rs is correctly implemented. It uses run_with_pty to execute the fg-p.sh script, which is appropriate for testing job control built-ins that may require a pseudo-terminal.

yash-env/src/job/fmt.rs (2)
  • 133-142: The addition of the number method to the Report struct in fmt.rs is a good example of encapsulation. It provides a clear and reusable way to obtain the job number, which is now used by the fmt method instead of calculating the number directly.

  • 151-151: The fmt method in the Report struct now correctly uses the new number method to obtain the job number. This change improves code readability and maintainability by centralizing the logic for determining the job number.

yash-builtin/src/lib.rs (5)
  • 50-50: The bg module has been correctly added to the public section of lib.rs. This change is necessary for the bg built-in command to be accessible as part of the shell's public interface.

  • 62-62: The fg module has been correctly added to the public section of lib.rs. This change is necessary for the fg built-in command to be accessible as part of the shell's public interface.

  • 118-122: The declaration of the bg built-in function is correctly implemented. It specifies the built-in type as Mandatory and provides the execution logic through the bg::main function.

  • 176-180: The declaration of the fg built-in function is correctly implemented. It specifies the built-in type as Mandatory and provides the execution logic through the fg::main function.

  • 299-299: The import of INode from yash_env::system::r#virtual in the tests module is correctly placed and necessary for the test setup, particularly for stubbing the TTY in tests.

yash-semantics/src/command/item.rs (3)
  • 79-82: The addition of the conditional check for job_control and the assignment of job.job_controlled seem appropriate for the context of asynchronous job execution. However, it's important to ensure that the job_control feature is thoroughly tested, especially since it affects job behavior.
Verification successful

The search using rg has successfully identified multiple instances in the codebase where job.job_controlled is set to true. These instances are found in various files, including item.rs, subshell.rs, pipeline.rs, external.rs, absent.rs, and multiple occurrences in fg.rs and bg.rs. This indicates that the job_controlled flag is indeed being set in the context of job control across different parts of the yash shell codebase.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify that job_controlled is set correctly in all relevant job instances.
ast-grep --lang rust --pattern $'let mut job = Job::new($_); $$$ job.job_controlled = $_;'

Length of output: 570



Script:

#!/bin/bash
# Simplify the pattern to match the structure of the Rust code for setting job_controlled
ast-grep --lang rust --pattern $'let mut job = Job::new($$$); job.job_controlled = true;'

Length of output: 568



Script:

#!/bin/bash
# Attempt a different approach to match the structure of the Rust code for setting job_controlled
ast-grep --lang rust --pattern $'let mut job = Job::new($_); job.job_controlled = true;'

Length of output: 566



Script:

#!/bin/bash
# Use ripgrep to search for the specific lines where `job.job_controlled` is set to true
rg "job.job_controlled = true"

Length of output: 1067

* 211-214: The assertions in the test `item_execute_async_job` are checking the job control flags and process IDs. It's crucial to verify that the job control flags are being set and used correctly throughout the codebase, as they can significantly affect the behavior of job execution.
Verification successful

The job_controlled flag is being set to true in various parts of the codebase, including yash-semantics and yash-builtin modules, and is checked in multiple test assertions. This confirms that the flag is an integral part of the job control mechanism and is being used as expected.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify that job_controlled is being checked correctly in all relevant parts of the codebase.
ast-grep --lang rust --pattern $'if $_.job_controlled { $$$ }'

Length of output: 63



Script:

#!/bin/bash
# Search for any occurrence of `job_controlled` in the codebase to understand its usage.
rg "job_controlled"

Length of output: 2833

* 274-274: The test `item_execute_async_background` checks if the job is correctly set as job-controlled when the Monitor option is on. This is a critical aspect of job control, and it's good to see it covered by a test.
yash-builtin/src/fg.rs (3)
  • 103-112: The wait_while_running function correctly loops to wait for a job to finish or suspend again. It's important to ensure that this loop does not cause any unintended side effects or resource exhaustion.

  • 120-155: The resume_job_by_index function handles the resumption of jobs by sending SIGCONT and waiting for the job to finish or suspend. It's important to ensure that the job control and signal sending are handled correctly, especially in a multi-threaded environment where race conditions could occur.

Verification successful

To verify the correct handling of job control and signal sending without race conditions, we need to adjust the ast-grep pattern to match the sequence of method calls in the resume_job_by_index function. Let's create a new script with a corrected pattern.


Given that the previous pattern did not yield results, I will simplify the pattern to match a broader range of possibilities within the resume_job_by_index function, focusing on the sequence of job control and signal sending.


Since the ast-grep approach has not been successful, I will switch to using ripgrep (rg) to search for the relevant lines of code directly within the resume_job_by_index function to verify the sequence of job control and signal sending.


The output from the rg command provides the contents of the resume_job_by_index function, but it does not include the entire function body. The output is truncated, and the critical parts of the function that involve sending the SIGCONT signal and handling job control are not visible.

To verify the review comment regarding the handling of job control and signal sending, we need to see the complete implementation of the resume_job_by_index function, specifically the sequence of operations after sending SIGCONT.

Given the incomplete information, I will generate a new script to retrieve the rest of the function body to ensure we can verify the correct handling of job control and signal sending.


The output from the rg command now provides the complete resume_job_by_index function from the yash-builtin/src/fg.rs file. The function includes the following sequence of operations:

  1. It retrieves the terminal group ID (tty).
  2. It accesses the job by index and checks if it is owned and job-controlled.
  3. It writes the job name to STDOUT.
  4. It checks if the job is alive; if not, it returns the job's status.
  5. It sets the target job to the foreground using tcsetpgrp_without_block before sending the SIGCONT signal to avoid immediate re-suspension.
  6. It sends the SIGCONT signal to the job's process group ID (pgid).
  7. It waits for the job to finish or suspend again using wait_while_running.
  8. It moves the shell back to the foreground using tcsetpgrp_with_block.

This sequence of operations is designed to handle job control and signal sending in a way that should prevent race conditions, such as making sure the job is in the foreground before sending SIGCONT and waiting for the job to finish or suspend again before proceeding.

Based on the provided code, the implementation appears to follow the correct sequence to handle job control and signal sending without race conditions. The review comment is consistent with the code implementation, and the function seems to be handling the resumption of jobs as expected.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify that the job control and signal sending are handled correctly without race conditions.
ast-grep --lang rust --pattern $'env.system.tcsetpgrp_without_block($$$); $$$ env.system.kill($$$, Signal::SIGCONT.into())?;'

Length of output: 640



Script:

#!/bin/bash
# Verify the sequence of job control and signal sending in the resume_job_by_index function.
ast-grep --lang rust --pattern $'fn resume_job_by_index($$$) {
  $$$
  env.system.tcsetpgrp_without_block($_, $_)?;
  $$$
  env.system.kill($_, Signal::SIGCONT.into())?;
  $$$
}'

Length of output: 179



Script:

#!/bin/bash
# Verify the sequence of job control and signal sending in the resume_job_by_index function by simplifying the pattern.
ast-grep --lang rust --pattern $'fn resume_job_by_index($$$) {
  $$$
  tcsetpgrp_without_block($$$);
  $$$
  kill($$$, Signal::SIGCONT.into())?;
  $$$
}'

Length of output: 154



Script:

#!/bin/bash
# Use ripgrep to search for the sequence of job control and signal sending in the resume_job_by_index function.
rg "fn resume_job_by_index" -A 20 yash-builtin/src/fg.rs

Length of output: 3731



Script:

#!/bin/bash
# Use ripgrep to search for the complete sequence of job control and signal sending in the resume_job_by_index function.
rg "async fn resume_job_by_index" -A 35 yash-builtin/src/fg.rs

Length of output: 1169

* 164-193: The `main` function of the `fg` built-in command correctly parses arguments and resumes the appropriate job. It's important to ensure that the error handling and exit status reporting are consistent with POSIX standards.
yash-builtin/src/bg.rs (9)
  • 17-79: The module documentation provides a clear overview of the bg built-in's functionality, including its purpose, usage, options, operands, output, errors, exit status, portability, and implementation notes. It is well-documented and follows the conventions for Rust documentation comments.

  • 80-107: The imports and dependencies section is well-organized and follows Rust conventions. All necessary modules and traits are imported for use in the file. There are no apparent issues with the imports.

  • 110-119: The ResumeError enum is well-defined and covers the potential errors that can occur when resuming a job. The use of thiserror for error handling is a good practice as it provides a convenient way to implement the Error trait for custom error types.

  • 121-132: The OperandErrorKind enum is similarly well-defined and covers errors related to processing operands. It is clear and concise, making it easy to understand the kinds of errors that can occur during operand processing.

  • 135-154: The OperandError struct and its implementation of the Display trait and MessageBase are correctly implemented. The struct associates an operand with its corresponding error, and the implementations provide a human-readable representation of the error, which is essential for good error reporting.

  • 156-162: The is_alive function is a simple and effective utility to check if a job's status indicates that it is still alive. The use of matches! macro makes the code concise and readable.

  • 164-200: The resume_job_by_index function is the core functionality for resuming a job by its index. It checks if the job is owned and job-controlled, formats a report line, writes to STDOUT, sends the SIGCONT signal if the job is alive, and sets the expected status. The function is well-structured and handles errors appropriately using the ? operator for early returns. The use of Pid::from_raw to create a negative process group ID (pgid) for sending the signal is correct as per POSIX conventions for signaling process groups.

  • 202-208: The resume_job_by_id function is a wrapper around resume_job_by_index that parses the job ID and finds the job index before resuming. It is concise and delegates the main functionality to resume_job_by_index, which is a good example of code reuse and separation of concerns.

  • 242-545: The test suite is comprehensive and covers various scenarios, including sending SIGCONT to the correct processes, printing job names, setting expected status, making the target the current job, handling dead processes, and rejecting unowned or unmonitored jobs. The tests for the main function cover resuming the current job, failing when there is no current job, resuming specified jobs, and attempting to resume all jobs even if some fail. The use of VirtualSystem for testing is a good practice as it allows for testing system interactions without affecting the actual system. The tests are well-structured and make good use of assertions to validate the behavior.

yash-env/src/job.rs (4)
  • 76-93: The addition of the expected_status field in the Job struct is a good way to manage job statuses more accurately. This field will help in determining if a job's status has changed in a meaningful way, which is crucial for job control.

  • 142-157: The expect method in the JobRefMut struct is a clean way to set the expected_status of a job. It's good to see that it uses generics to allow for None values as well, providing flexibility in usage.

  • 584-617: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [566-614]

The logic in the update_status method of the JobSet struct correctly handles the new expected_status field. It sets the status_changed flag only if the new status does not match the expected_status, which is a sensible approach. However, ensure that all callers of this method are aware of the new behavior and that they set the expected_status appropriately before calling update_status.

  • 871-912: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [853-908]

The tests have been updated to cover the new expected_status functionality. They check for cases where the expected_status matches the actual status, where it does not match, and where there is no expected_status set. This is a comprehensive approach to testing the new feature.

yash-env/src/system/virtual.rs (3)
  • 937-943: The refactoring of send_signal_to_processes to use a results vector is a good change for clarity and future maintenance. It's important to ensure that the logic for sending signals and handling the results remains correct.

  • 948-954: The logic for checking the results of signal operations and raising SIGCHLD if the process state changed is correct. This ensures that parent processes are notified of child process state changes.

  • 1768-1786: The new test kill_returns_success_even_if_process_state_did_not_change is well-named and clearly tests the behavior described in the summary. It's important to ensure that the test covers all relevant cases and that the assertions are valid.

Comment on lines +210 to +240
/// Entry point of the `bg` built-in
pub async fn main(env: &mut Env, args: Vec<Field>) -> crate::Result {
let (options, operands) = match parse_arguments(&[], Mode::with_env(env), args) {
Ok(result) => result,
Err(error) => return report_error(env, &error).await,
};
debug_assert_eq!(options, []);

if operands.is_empty() {
if let Some(index) = env.jobs.current_job() {
match resume_job_by_index(env, index).await {
Ok(()) => crate::Result::default(),
Err(error) => report_simple_failure(env, &error.to_string()).await,
}
} else {
report_simple_failure(env, "there is no job").await
}
} else {
let mut errors = Vec::new();
for operand in operands {
match resume_job_by_id(env, &operand.value).await {
Ok(()) => {}
Err(error) => errors.push(OperandError(operand, error)),
}
}
match to_single_message(&{ errors }) {
None => crate::Result::default(),
Some(message) => report_failure(env, message).await,
}
}
}
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main function serves as the entry point for the bg built-in. It parses arguments, handles the case where no operands are provided by resuming the current job, and iterates over operands to resume specified jobs. Error handling is done by collecting errors into a vector and then reporting them. The function is well-structured and follows Rust's async conventions. However, the debug assertion on line 216 assumes that the options will always be empty, which might not be future-proof if options are added later.

Consider removing the debug assertion or updating it to account for potential future options for the bg command.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suppose you are saying the same thing as in this comment: https://github.com/magicant/yash-rs/pull/339/files#r1444715571

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicant It appears that the referenced comment is indeed similar to the one I made, both addressing the potential future-proofing issue with the debug assertion on line 216 in bg.rs. The assertion checks for empty options, which could lead to problems if options are introduced later. It's a good practice to anticipate such changes to maintain code robustness.

Would you like me to remember this preference for handling future-proofing in code assertions for subsequent reviews?

Analysis chain
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Retrieve the content of the comment referenced by the user.
gh api -X GET repos/magicant/yash-rs/pulls/comments/1444715571

Length of output: 10167

Comment on lines +1 to +78
# fg-p.sh: test of the fg built-in for any POSIX-compliant shell

posix="true"

cat >job1 <<\__END__
exec sh -c 'echo 1; kill -s STOP $$; echo 2'
__END__

cat >job2 <<\__END__
exec sh -c 'echo a; kill -s STOP $$; echo b'
__END__

chmod a+x job1
chmod a+x job2

mkfifo fifo

test_O -d -e n 'fg cannot be used when job control is disabled' +m
:&
fg
__IN__

test_oE 'default operand chooses most recently suspended job' -m
:&
sh -c 'kill -s STOP $$; echo 1'
fg >/dev/null
__IN__
1
__OUT__

: TODO Needs to find a way to test this <<\__IN__
test_oE 'resumed job is in foreground' -m
sh -c 'kill -s STOP $$; ...'
fg >/dev/null
__IN__

: TODO Needs the kill built-in <<\__IN__
test_x -e 127 'resumed job is disowned unless suspended again' -m
cat fifo >/dev/null &
exec 3>fifo
kill -s STOP %
exec 3>&-
fg >/dev/null
wait $!
__IN__

test_oE 'specifying job ID' -m
./job1
./job2
fg %./job1 >/dev/null
fg %./job2 >/dev/null
__IN__
1
a
2
b
__OUT__

test_oE 'fg prints resumed job' -m
./job1
fg
__IN__
1
./job1
2
__OUT__

test_O -d -e n 'no existing job' -m
fg
__IN__

test_O -d -e n 'no such job' -m
sh -c 'kill -s STOP $$'
fg %_no_such_job_
exit_status=$?
fg >/dev/null
exit $exit_status
__IN__
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script fg-p.sh is well-structured and covers various test cases for the fg built-in command. It includes tests for default operand selection, job resumption, and proper exit status reporting. However, there are two TODO comments indicating incomplete test cases that need to be addressed.

  • Line 31: The test case for checking if a resumed job is in the foreground is marked as TODO and needs to be implemented.
  • Line 37: The test case for checking if a resumed job is disowned unless suspended again is also marked as TODO and requires the kill built-in for completion.

It's important to implement these tests to ensure comprehensive coverage of the fg functionality.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll address them later as I described in other comments.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicant Understood, the incomplete test cases will be addressed in the future as you've indicated. If there's anything else you need in the meantime, feel free to let me know!


If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

Comment on lines +1 to +103

# The "sleep 0" commands in the test cases below are a hack to ensure that the
# shell receives SIGCHLD and takes in the latest status of the background jobs.
# Without this, the "wait" built-in may return before the background jobs are
# actually resumed.

cat >job1 <<\__END__
exec sh -c 'kill -s STOP $$; echo'
__END__

chmod a+x job1
ln job1 job2

test_O -d -e n 'bg cannot be used when job control is disabled' +m
:&
bg
__IN__

test_oE 'default operand chooses most recently suspended job' -m
:&
sh -c 'kill -s STOP $$; echo 1'
bg >/dev/null
sleep 0
wait
__IN__
1
__OUT__

: TODO Needs the kill built-in <<\__IN__
test_OE 'already running job is ignored' -m
while kill -s CONT $$; do sleep 1; done &
bg >/dev/null
kill %
__IN__

test_OE -e 17 'resumed job is awaitable' -m
sh -c 'kill -s STOP $$; exit 17'
bg >/dev/null
sleep 0
wait %
__IN__

test_O -e n 'resumed job is in background' -m
sh -c 'kill -s STOP $$; trap "" TTIN; head -n 1 /dev/tty'
# The shell is ignoring SIGTTIN, so the "head" command will just fail with EIO
# when it tries to read from the terminal in the background.
bg >/dev/null
sleep 0
wait %
__IN__

test_oE 'specifying job ID' -m
./job1
./job2
echo -
bg %./job1 >/dev/null
bg %./job2 >/dev/null
sleep 0
wait
__IN__
-


__OUT__

test_oE 'specifying more than one job ID' -m
./job1
./job2
echo -
bg %./job1 %./job2 >/dev/null
sleep 0
wait
__IN__
-


__OUT__

test_OE -e 0 'bg prints resumed job' -m
sleep 1&
bg >bg.out
grep -qx '\[[[:digit:]][[:digit:]]*][[:blank:]]*sleep 1' bg.out
__IN__

test_OE -e 0 'exit status of bg' -m
sh -c 'kill -s STOP $$; exit 17'
bg >/dev/null
__IN__

test_O -d -e n 'no existing job' -m
bg
__IN__

test_O -d -e n 'no such job' -m
sh -c 'kill -s STOP $$'
bg %_no_such_job_
exit_status=$?
fg >/dev/null
exit $exit_status
__IN__
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script bg-p.sh is well-structured and covers various test cases for the bg built-in command. It includes tests for default operand selection, job resumption, and proper exit status reporting. However, there is a TODO comment indicating an incomplete test case that needs to be addressed.

  • Line 32: The test case for checking if an already running job is ignored is marked as TODO and requires the kill built-in for completion.

It's important to implement this test to ensure comprehensive coverage of the bg functionality.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll address this when the kill built-in is implemented.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rate Limit Exceeded

@magicant have exceeded the limit for the number of chat messages per hour. Please wait 2 minutes and 19 seconds before sending another message.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 0

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 460412e and e6e4a98.
Files selected for processing (10)
  • yash-builtin/src/bg.rs (1 hunks)
  • yash-builtin/src/fg.rs (1 hunks)
  • yash-builtin/src/lib.rs (6 hunks)
  • yash-env/src/job.rs (7 hunks)
  • yash-env/src/job/fmt.rs (1 hunks)
  • yash-env/src/system/virtual.rs (2 hunks)
  • yash-semantics/src/command/item.rs (3 hunks)
  • yash/tests/scripted_test.rs (2 hunks)
  • yash/tests/scripted_test/bg-p.sh (1 hunks)
  • yash/tests/scripted_test/fg-p.sh (1 hunks)
Files skipped from review as they are similar to previous changes (9)
  • yash-builtin/src/bg.rs
  • yash-builtin/src/fg.rs
  • yash-env/src/job.rs
  • yash-env/src/job/fmt.rs
  • yash-env/src/system/virtual.rs
  • yash-semantics/src/command/item.rs
  • yash/tests/scripted_test.rs
  • yash/tests/scripted_test/bg-p.sh
  • yash/tests/scripted_test/fg-p.sh
Additional comments: 6
yash-builtin/src/lib.rs (6)
  • 50-50: The addition of the bg module to the public section is consistent with the PR objectives to implement the bg built-in command.

  • 62-62: The addition of the fg module to the public section aligns with the PR objectives to implement the fg built-in command.

  • 117-122: The declaration of the bg built-in function is correct and follows the established pattern for built-in commands in this project. The execute lambda correctly references the bg::main function.

  • 176-180: The declaration of the fg built-in function is also correct and follows the same pattern as other built-ins. The execute lambda correctly references the fg::main function.

  • 298-298: The import of INode within the tests module is appropriate for the test setup, allowing for the creation of virtual file system nodes.

  • 352-358: The stub_tty function has been added to the tests module, which creates a stub for /dev/tty in the virtual file system. This is likely used for testing built-ins that interact with the terminal. Ensure that this stub is used appropriately in tests that require a terminal interface.

Verification successful

The stub_tty function is used across various test files, indicating that it is indeed utilized for simulating terminal interaction within tests. This aligns with the review comment's expectation that the stub should be used in tests requiring a terminal interface.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify that the stub_tty function is used in tests that simulate terminal interaction.
rg --type rust 'stub_tty'

Length of output: 1869

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Status

Actionable comments generated: 14

Configuration used: CodeRabbit UI

Commits Files that changed from the base of the PR and between 460412e and 4773aa4.
Files selected for processing (10)
  • yash-builtin/src/bg.rs (1 hunks)
  • yash-builtin/src/fg.rs (1 hunks)
  • yash-builtin/src/lib.rs (6 hunks)
  • yash-env/src/job.rs (7 hunks)
  • yash-env/src/job/fmt.rs (1 hunks)
  • yash-env/src/system/virtual.rs (2 hunks)
  • yash-semantics/src/command/item.rs (3 hunks)
  • yash/tests/scripted_test.rs (2 hunks)
  • yash/tests/scripted_test/bg-p.sh (1 hunks)
  • yash/tests/scripted_test/fg-p.sh (1 hunks)
Additional comments: 34
yash/tests/scripted_test/fg-p.sh (3)
  • 23-30: The test case for the default operand choosing the most recently suspended job is well-structured and includes both input and expected output.

  • 47-57: The test case for specifying job ID is complete and correctly checks for the expected output after resuming jobs with fg.

  • 59-66: The test case for ensuring fg prints the resumed job is well-implemented, with clear input and output expectations.

yash/tests/scripted_test/bg-p.sh (6)
  • 22-30: The test case for the default operand choosing the most recently suspended job is well-structured and includes both input and expected output.

  • 39-44: The test case for ensuring a resumed job is awaitable is complete and correctly checks for the expected exit status after resuming a job with bg.

  • 46-53: The test case for verifying that a resumed job is in the background is well-implemented, with a clear setup and expected behavior.

  • 55-67: The test case for specifying job ID is complete and correctly checks for the expected output after resuming jobs with bg.

  • 69-80: The test case for specifying more than one job ID is complete and correctly checks for the expected output after resuming multiple jobs with bg.

  • 82-86: The test case for ensuring bg prints the resumed job is well-implemented, with clear input and output expectations.

yash/tests/scripted_test.rs (2)
  • 96-99: The new test function bg_builtin has been added correctly and uses run_with_pty to execute the bg-p.sh script.

  • 151-154: The new test function fg_builtin has been added correctly and uses run_with_pty to execute the fg-p.sh script.

yash-env/src/job/fmt.rs (2)
  • 133-142: The addition of the number method to the Report struct is a good enhancement for code readability and maintainability. It encapsulates the logic for calculating the job number.

  • 151-151: The fmt method in the Display implementation for Report has been updated to use the new number method. This change is consistent with the addition of the number method and maintains the functionality of the fmt method.

yash-builtin/src/lib.rs (5)
  • 50-50: The addition of the bg module to the public interface is noted and aligns with the PR objectives.

  • 62-62: The addition of the fg module to the public interface is also noted and aligns with the PR objectives.

  • 117-122: The bg built-in command has been added to the BUILTINS constant with the correct type and execution function.

  • 176-181: The fg built-in command has been added to the BUILTINS constant with the correct type and execution function.

  • 114-126: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [117-181]

Please ensure that the bg and fg built-in commands are inserted in the correct alphabetical order within the BUILTINS array to maintain consistency and pass the builtins_are_sorted test.

Verification successful

The bg and fg built-in commands are inserted in the correct alphabetical order within the BUILTINS array in yash-builtin/src/lib.rs. The bg command is correctly placed before break, and the fg command is correctly placed after export and before getopts.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Verify the order of built-in commands in the BUILTINS array.
rg --type rust --fixed-strings 'pub const BUILTINS: &[(&str, Builtin)] = &['

Length of output: 146



Script:

#!/bin/bash
# Extract the contents of the BUILTINS array to verify the order of built-in commands.
rg --type rust --fixed-strings 'pub const BUILTINS: &[(&str, Builtin)] = &[' -A 30

Length of output: 1535



Script:

#!/bin/bash
# Extract more lines following the BUILTINS array declaration to verify the order of built-in commands.
rg --type rust --fixed-strings 'pub const BUILTINS: &[(&str, Builtin)] = &[' -A 50

Length of output: 2480



Script:

#!/bin/bash
# Extract even more lines following the BUILTINS array declaration to verify the order of built-in commands.
rg --type rust --fixed-strings 'pub const BUILTINS: &[(&str, Builtin)] = &[' -A 100

Length of output: 4835

yash-semantics/src/command/item.rs (3)
  • 79-82: The conditional block added to set the job_controlled flag in the Job struct based on the job_control value is a logical change that aligns with the PR objectives.

  • 211-214: The new assertions in the test module correctly check the job_controlled flag and other job attributes, ensuring that the job control functionality is tested as expected.

  • 274-274: The assertion that checks if the job is controlled (job_controlled) after executing an asynchronous command in the background is appropriate and ensures that job control is being applied correctly.

yash-builtin/src/fg.rs (6)
  • 103-112: The wait_while_running function correctly loops until the job is no longer running. It handles the Continued and StillAlive statuses appropriately, resuming the loop in those cases, and returns the status otherwise.

  • 157-162: The resume_job_by_id function parses the job ID and finds the job index, then delegates to resume_job_by_index. It's a straightforward function that correctly handles the delegation.

  • 242-242: The test resume_job_by_index_sends_no_sigcont_to_dead_process correctly verifies that no SIGCONT signal is sent to a process that has already exited. This is an important check to ensure that the shell does not inadvertently signal the wrong process.

  • 273-284: The test resume_job_by_index_rejects_unowned_job correctly asserts that an error is returned when attempting to resume a job that is not owned by the current shell environment. This is a good test for ensuring proper error handling in the fg built-in.

  • 287-294: The test resume_job_by_index_rejects_unmonitored_job correctly asserts that an error is returned when attempting to resume a job that is not job-controlled. This is another good test for ensuring proper error handling in the fg built-in.

  • 304-314: The test main_without_operands_fails_if_there_is_no_current_job correctly asserts that the fg built-in fails with an appropriate error message when there is no current job to resume. This test ensures that the built-in behaves correctly in the absence of a current job.

yash-builtin/src/bg.rs (1)
  • 242-545: The test suite is comprehensive and covers a variety of scenarios, including signal sending, job status updates, and error handling. The use of VirtualSystem for testing is appropriate as it avoids affecting the real system state. Good job ensuring that the tests cover the functionality of the bg built-in command.
yash-env/src/job.rs (4)
  • 89-92: The addition of the expected_status field in the Job struct is a good way to track the anticipated state of a job, which can help in making decisions based on the job's lifecycle. Ensure that the logic that interacts with this field is well-tested, especially in edge cases where job statuses might change unexpectedly.

  • 142-157: The expect method in JobRefMut provides a controlled way to set the expected_status of a job. It's important to ensure that this method is used consistently across the codebase to manage job statuses.

  • 584-617: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [566-614]

The update_status method in JobSet has been correctly updated to account for the new expected_status field. This change should help in accurately reflecting job status changes and in suppressing unnecessary status change notifications when the actual status matches the expected one. It's crucial to verify that all possible status transitions are handled correctly and that the status_changed flag is set or cleared appropriately.

  • 871-912: > Note: This review was outside the patches, so it was mapped to the patch with the greatest overlap. Original lines [853-908]

The new tests for updating job status with and without expected_status seem comprehensive. It's important to ensure that these tests cover all the scenarios that might occur in real usage, including concurrent updates and race conditions that could affect the job status.

yash-env/src/system/virtual.rs (2)
  • 937-951: The refactoring of send_signal_to_processes to use a results vector is a logical change that enhances the clarity of the code by directly associating the result of the signal operation with the parent process ID. This change should make it easier to understand the flow of signal handling within the system.

  • 1768-1786: The addition of the test kill_returns_success_even_if_process_state_did_not_change is a good practice to ensure that the kill function behaves correctly even when the process state does not change after sending a signal. This test helps to prevent regressions in the signal handling logic.

Ok(result) => result,
Err(error) => return report_error(env, &error).await,
};
debug_assert_eq!(options, []);
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The debug assertion on line 216 assumes that the options will always be empty. If there's a possibility that options might be added to the bg command in the future, this assertion could cause issues. Consider removing it or updating it to account for potential options.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have no plan for supporting any options in the bg built-in, so I leave the assertion as is. If we add any options in the future, we have to update the code somehow, so I think it is very unlikely to forget to remove the assertion then.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicant, understood. Keeping the assertion makes sense given the current design decisions and future plans for the bg built-in. Thank you for the clarification.

🎉

🐇


New Learnings Added
User: magicant
PR: magicant/yash-rs#339
File: yash-builtin/src/bg.rs:216-216
Timestamp: 2024-01-08T15:44:15.403Z
Learning: The user has clarified that there are no plans to support options in the `bg` built-in command and intends to leave the debug assertion as is, with the understanding that if options are added in the future, the code will be updated accordingly, which would include removing the assertion.

If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

Comment on lines +120 to +154
async fn resume_job_by_index(env: &mut Env, index: usize) -> Result<WaitStatus, ResumeError> {
let tty = env.get_tty()?;

let job = env.jobs.get(index).unwrap();
if !job.is_owned {
return Err(ResumeError::Unowned);
}
if !job.job_controlled {
return Err(ResumeError::Unmonitored);
}

let line = format!("{}\n", job.name);
env.system.write_all(Fd::STDOUT, line.as_bytes()).await?;
drop(line);

if !is_alive(job.status) {
return Ok(job.status);
}

// TODO Should we save/restore the terminal state?

// Make sure to put the target job in the foreground before sending the
// SIGCONT signal, or the job may be immediately re-suspended.
env.system.tcsetpgrp_without_block(tty, job.pid)?;

let pgid = Pid::from_raw(-job.pid.as_raw());
env.system.kill(pgid, Signal::SIGCONT.into())?;

// Wait for the job to finish (or suspend again).
let status = wait_while_running(env, job.pid).await?;

// Move the shell back to the foreground.
env.system.tcsetpgrp_with_block(tty, env.main_pgid)?;

Ok(status)
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The resume_job_by_index function has several responsibilities: it retrieves the TTY, ensures the job is owned and job-controlled, writes the job name to stdout, checks if the job is alive, sends the SIGCONT signal, and waits for the job to finish or suspend again. It also moves the shell back to the foreground after the job status is resolved. The logic appears sound, but there is a TODO comment regarding saving/restoring the terminal state (line 139) which should be addressed or tracked in an issue for future implementation.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the reminder. Added an item in #265 to track this TODO comment.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rate Limit Exceeded

@magicant have exceeded the limit for the number of chat messages per hour. Please wait 2 minutes and 20 seconds before sending another message.

Comment on lines +164 to +192
/// Entry point of the `fg` built-in
pub async fn main(env: &mut Env, args: Vec<Field>) -> crate::Result {
let (options, operands) = match parse_arguments(&[], Mode::with_env(env), args) {
Ok(result) => result,
Err(error) => return report_error(env, &error).await,
};
debug_assert_eq!(options, []);

let result = if operands.is_empty() {
if let Some(index) = env.jobs.current_job() {
resume_job_by_index(env, index).await.map_err(Into::into)
} else {
return report_simple_failure(env, "there is no job").await;
}
} else if operands.len() > 1 {
// TODO Support multiple operands
return report_simple_failure(env, "too many operands").await;
} else {
resume_job_by_id(env, &operands[0].value).await
};

match result {
Ok(WaitStatus::Exited(_, exit_status)) => crate::Result::from(ExitStatus(exit_status)),
Ok(WaitStatus::Signaled(_, signal, _)) | Ok(WaitStatus::Stopped(_, signal)) => {
crate::Result::from(ExitStatus::from(signal))
}
Ok(wait_status) => unreachable!("unexpected wait status: {wait_status:?}"),
Err(error) => report_simple_failure(env, &error.to_string()).await,
}
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The main function of the fg built-in parses arguments, handles the case of no operands by resuming the current job, and handles the case of one operand by resuming the specified job. It correctly returns the exit status of the resumed job or an error message. However, there is a TODO comment regarding support for multiple operands (line 179) which should be addressed or tracked in an issue for future implementation.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The TODO is already tracked in #265

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicant It appears there are several other TODO comments in fg.rs that may need to be tracked or addressed:

  1. Allowing the omission of the leading % in job IDs.
  2. Printing the job number as well as the name to the standard output.
  3. Considering whether to save/restore the terminal state.
  4. Implementing and testing various functionalities, including:
    • Moving the job to the foreground (resume_job_by_index_moves_job_to_foreground).
    • Sending SIGCONT signal (resume_job_by_index_sends_sigcont).
    • Printing the job name (resume_job_by_index_prints_job_name).
    • Returning after job exits (resume_job_by_index_returns_after_job_exits).
    • Returning after job suspends (resume_job_by_index_returns_after_job_suspends).
    • Moving the shell back to the foreground (resume_job_by_index_moves_shell_back_to_foreground).
    • Resuming the current job without operands (main_without_operands_resumes_current_job).
    • Resuming the specified job with operand (main_with_operands_resumes_specified_job).
    • Error cases with operands.

Would you like to open new GitHub issues for these items, or are they already tracked elsewhere?

Analysis chain

@magicant Thank you for the update. I'll keep in mind that the TODO for supporting multiple operands in the fg built-in is tracked in issue #265.

Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Check if there are any other TODOs or similar comments that need to be addressed in fg.rs
rg -C 3 "TODO" yash-builtin/src/fg.rs

Length of output: 2351

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unimplemented tests are tracked in #340. The other TODOs are tracked in #265.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicant Understood, all the mentioned TODOs are being tracked in issues #265 and #340. No further action is required at this moment. Thank you for the clarification.

🎉

🐇


New Learnings Added
User: magicant
PR: magicant/yash-rs#339
File: yash-builtin/src/fg.rs:164-192
Timestamp: 2024-01-08T16:01:10.335Z
Learning: The unimplemented tests in `fg.rs` are tracked in issue #340, and other TODOs are tracked in issue #265.

If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

Comment on lines +206 to +242
#[test]
#[ignore = "not implemented"]
fn resume_job_by_index_moves_job_to_foreground() {
// TODO Test resume_job_by_index_moves_job_to_foreground
}

#[test]
#[ignore = "not implemented"]
fn resume_job_by_index_sends_sigcont() {
// TODO Test resume_job_by_index_sends_sigcont
}

#[test]
fn resume_job_by_index_prints_job_name() {
// TODO Test resume_job_by_index_prints_job_name
}

#[test]
#[ignore = "not implemented"]
fn resume_job_by_index_returns_after_job_exits() {
// TODO Test resume_job_by_index_returns_after_job_exits
}

#[test]
#[ignore = "not implemented"]
fn resume_job_by_index_returns_after_job_suspends() {
// TODO Test resume_job_by_index_returns_after_job_suspends
}

#[test]
#[ignore = "not implemented"]
fn resume_job_by_index_moves_shell_back_to_foreground() {
// TODO resume_job_by_index_moves_shell_back_to_foreground
}

#[test]
fn resume_job_by_index_sends_no_sigcont_to_dead_process() {
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The tests section contains several ignored tests with TODO comments indicating that they are not implemented. These tests are crucial for ensuring the correct behavior of the fg built-in, especially for edge cases. It is important to implement these tests before merging the PR.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I chose not to implement those test cases in this pull request because it requires fine-grained control over processes in the VirtualSystem, which is not yet supported. This is tracked in #340

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicant Understood. Would you like to include a reference to issue #340 in the TODO comments for the unimplemented tests? This could provide context and link the tests to the required VirtualSystem enhancements for anyone reviewing the code later on.

Comment on lines +18 to +21
test_O -d -e n 'fg cannot be used when job control is disabled' +m
:&
fg
__IN__
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case for checking if fg can be used when job control is disabled seems to be incomplete. The test command is run, but there is no assertion or check to verify the expected behavior.

- :&
- fg
+ :&
+ fg
+ # Expected behavior check should be here

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
test_O -d -e n 'fg cannot be used when job control is disabled' +m
:&
fg
__IN__
test_O -d -e n 'fg cannot be used when job control is disabled' +m
:&
fg
# Expected behavior check should be here
__IN__

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The options for the test case command are specifying the expected behaviors. The -d option requires a non-empty output to the standard error. The -e n option requires a non-zero exit status. See the yash/tests/scripted_test/run-test.sh file to learn how these options are defined and implemented.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicant Thank you for the clarification. I've reviewed the run-test.sh script and understand how the -d and -e n options function to specify the expected behaviors for the test case. It seems everything is in order, and no changes are required for the test case in question.

Analysis chain
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Display the contents of run-test.sh to understand the implementation of the test case options.
cat yash/tests/scripted_test/run-test.sh

Length of output: 12467


New Learnings Added
User: magicant
PR: magicant/yash-rs#339
File: yash/tests/scripted_test/fg-p.sh:18-21
Timestamp: 2024-01-08T15:45:36.866Z
Learning: The `run-test.sh` script in the `yash` repository uses the `-d` option to require non-empty output to standard error and the `-e n` option to require a non-zero exit status in test cases.

If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

Comment on lines +17 to +20
test_O -d -e n 'bg cannot be used when job control is disabled' +m
:&
bg
__IN__
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case for checking if bg can be used when job control is disabled seems to be incomplete. The test command is run, but there is no assertion or check to verify the expected behavior.

- :&
- bg
+ :&
+ bg
+ # Expected behavior check should be here

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
test_O -d -e n 'bg cannot be used when job control is disabled' +m
:&
bg
__IN__
test_O -d -e n 'bg cannot be used when job control is disabled' +m
:&
bg
# Expected behavior check should be here
__IN__

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The options for the test case command are specifying the expected behaviors. The -d option requires a non-empty output to the standard error. The -e n option requires a non-zero exit status. See the yash/tests/scripted_test/run-test.sh file to learn how these options are defined and implemented.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rate Limit Exceeded

@magicant have exceeded the limit for the number of chat messages per hour. Please wait 2 minutes and 16 seconds before sending another message.

Comment on lines +32 to +37
: TODO Needs the kill built-in <<\__IN__
test_OE 'already running job is ignored' -m
while kill -s CONT $$; do sleep 1; done &
bg >/dev/null
kill %
__IN__
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case for checking if an already running job is ignored is marked as TODO. This test is important for ensuring that bg behaves correctly when dealing with running jobs.

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll address this when the kill built-in is implemented.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rate Limit Exceeded

@magicant have exceeded the limit for the number of chat messages per hour. Please wait 2 minutes and 21 seconds before sending another message.

Comment on lines +88 to +91
test_OE -e 0 'exit status of bg' -m
sh -c 'kill -s STOP $$; exit 17'
bg >/dev/null
__IN__
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case for checking the exit status of bg is incomplete. It should include an assertion to check the expected exit status after running bg.

- bg >/dev/null
+ bg >/dev/null
+ # Expected exit status check should be here

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
test_OE -e 0 'exit status of bg' -m
sh -c 'kill -s STOP $$; exit 17'
bg >/dev/null
__IN__
test_OE -e 0 'exit status of bg' -m
sh -c 'kill -s STOP $$; exit 17'
bg >/dev/null
# Expected exit status check should be here
__IN__

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The option for the test case command is specifying the expected behavior. The -e 0 option requires the exit status to be 0. See the yash/tests/scripted_test/run-test.sh file to learn how these options are defined and implemented.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rate Limit Exceeded

@magicant have exceeded the limit for the number of chat messages per hour. Please wait 2 minutes and 21 seconds before sending another message.

Comment on lines +93 to +95
test_O -d -e n 'no existing job' -m
bg
__IN__
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case for handling the scenario where there is no existing job for bg to operate on is incomplete. It should include an assertion to check the expected failure message or exit status.

- bg
+ bg
+ # Expected failure assertion should be here

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
test_O -d -e n 'no existing job' -m
bg
__IN__
test_O -d -e n 'no existing job' -m
bg
# Expected failure assertion should be here
__IN__

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The options for the test case command are specifying the expected behaviors. The -d option requires a non-empty output to the standard error. The -e n option requires a non-zero exit status. See the yash/tests/scripted_test/run-test.sh file to learn how these options are defined and implemented.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicant Thank you for the clarification. I've reviewed the run-test.sh script and understand how the -d and -e n options are used to specify the expected behaviors for non-empty standard error output and non-zero exit status, respectively. Your explanation aligns with the script's implementation of these options.

🐰🔍

Analysis chain
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Display the contents of run-test.sh to understand the test case options.
cat yash/tests/scripted_test/run-test.sh

Length of output: 12467

Comment on lines +97 to +103
test_O -d -e n 'no such job' -m
sh -c 'kill -s STOP $$'
bg %_no_such_job_
exit_status=$?
fg >/dev/null
exit $exit_status
__IN__
Copy link

@coderabbitai coderabbitai bot Jan 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test case for handling a non-existent job is partially complete. It correctly sets up a scenario where bg is called with an invalid job ID, but it lacks an assertion to verify the exit status or error message.

- bg %_no_such_job_
- exit_status=$?
- fg >/dev/null
- exit $exit_status
+ bg %_no_such_job_
+ exit_status=$?
+ # Expected error message or exit status check should be here

Committable suggestion

IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation.

Suggested change
test_O -d -e n 'no such job' -m
sh -c 'kill -s STOP $$'
bg %_no_such_job_
exit_status=$?
fg >/dev/null
exit $exit_status
__IN__
test_O -d -e n 'no such job' -m
sh -c 'kill -s STOP $$'
bg %_no_such_job_
exit_status=$?
# Expected error message or exit status check should be here
__IN__

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The options for the test case command are specifying the expected behaviors. The -d option requires a non-empty output to the standard error. The -e n option requires a non-zero exit status. See the yash/tests/scripted_test/run-test.sh file to learn how these options are defined and implemented.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@magicant Thank you for the clarification. I've reviewed the run-test.sh script and understand how the -d and -e n options are designed to assert the expected standard error output and non-zero exit status, respectively. The test case in question is indeed complete as it stands, with the script handling the assertions internally based on the provided options. No further action is required for this test case.

🎉

Analysis chain
Scripts executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Display the contents of the run-test.sh script to understand the implementation of test case options.
cat yash/tests/scripted_test/run-test.sh

Length of output: 12467


New Learnings Added
User: magicant
PR: magicant/yash-rs#339
File: yash/tests/scripted_test/bg-p.sh:97-103
Timestamp: 2024-01-08T15:45:07.471Z
Learning: The user has clarified that the `-d` option in the `yash/tests/scripted_test/run-test.sh` script requires a non-empty output to the standard error, and the `-e n` option requires a non-zero exit status. This information is crucial for understanding how test cases are asserted within the `yash` shell's testing framework.

If you found this review helpful, would you consider giving us a shout-out on X?
Thank you for using CodeRabbit!

@magicant magicant merged commit c8b0b5e into master Jan 9, 2024
5 checks passed
@magicant magicant deleted the fg-builtin branch January 9, 2024 15:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Done
Development

Successfully merging this pull request may close these issues.

1 participant