Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,3 @@ jobs:
uses: innmind/github-workflows/.github/workflows/psalm-matrix.yml@main
cs:
uses: innmind/github-workflows/.github/workflows/cs.yml@main
with:
php-version: '8.2'
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## [Unreleased]

### Changed

- Requires PHP `8.4`
- Requires `innmind/foundation:~2.1`

## 4.0.0 - 2025-08-07

### Changed
Expand Down
9 changes: 3 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
"issues": "http://github.com/Innmind/Cron/issues"
},
"require": {
"php": "~8.2",
"innmind/foundation": "~1.5"
"php": "~8.4",
"innmind/foundation": "~2.1"
},
"autoload": {
"psr-4": {
Expand All @@ -29,11 +29,8 @@
}
},
"require-dev": {
"innmind/static-analysis": "^1.2.1",
"innmind/static-analysis": "~1.3",
"innmind/black-box": "~6.5",
"innmind/coding-standard": "~2.0"
},
"suggest": {
"innmind/operating-system": "To easily access to a machine control mechanism"
}
}
2 changes: 1 addition & 1 deletion src/Read.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function __invoke(Server $server): Attempt
static fn($success) => $success
->output()
->map(static fn($chunk) => $chunk->data())
->fold(new Concat)
->fold(Concat::monoid)
->split("\n")
->filter(static fn($line) => !$line->startsWith('#') && !$line->trim()->empty())
->map(static fn($line) => Job::attempt($line->toString())),
Expand Down
78 changes: 49 additions & 29 deletions tests/CrontabTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,36 +7,48 @@
Crontab,
Job,
};
use Innmind\Server\Control\Servers\Mock;
use Innmind\Immutable\SideEffect;
use Innmind\Server\Control\{
Server,
Server\Process\Builder,
};
use Innmind\Immutable\{
Attempt,
SideEffect,
};
use Innmind\BlackBox\PHPUnit\Framework\TestCase;

class CrontabTest extends TestCase
{
public function testInstallEmptyCrontabForConnectedUser()
{
$crontab = Crontab::forConnectedUser();
$server = Mock::new($this->assert())
->willExecute(
fn($command) => $this->assertSame(
$server = Server::via(
function($command) {
$this->assertSame(
"crontab '-r'",
$command->toString(),
),
);
);

return Attempt::result(Builder::foreground(2)->build());
},
);

$this->assertInstanceOf(SideEffect::class, $crontab($server)->unwrap());
}

public function testInstallEmptyCrontabForSpecificUser()
{
$crontab = Crontab::forUser('admin');
$server = Mock::new($this->assert())
->willExecute(
fn($command) => $this->assertSame(
$server = Server::via(
function($command) {
$this->assertSame(
"crontab '-u' 'admin' '-r'",
$command->toString(),
),
);
);

return Attempt::result(Builder::foreground(2)->build());
},
);

$this->assertInstanceOf(SideEffect::class, $crontab($server)->unwrap());
}
Expand All @@ -47,13 +59,16 @@ public function testInstallCrontabForConnectedUser()
Job::of('1 2 3 4 5 echo foo'),
Job::of('2 3 4 5 6 echo bar'),
);
$server = Mock::new($this->assert())
->willExecute(
fn($command) => $this->assertSame(
"echo '1 2 3 4 5 echo foo\n2 3 4 5 6 echo bar' | 'crontab'",
$server = Server::via(
function($command) {
$this->assertSame(
"echo '1 2 3 4 5 echo foo\n2 3 4 5 6 echo bar' | crontab",
$command->toString(),
),
);
);

return Attempt::result(Builder::foreground(2)->build());
},
);

$this->assertInstanceOf(SideEffect::class, $crontab($server)->unwrap());
}
Expand All @@ -65,13 +80,16 @@ public function testInstallCrontabForSpecificUser()
Job::of('1 2 3 4 5 echo foo'),
Job::of('2 3 4 5 6 echo bar'),
);
$server = Mock::new($this->assert())
->willExecute(
fn($command) => $this->assertSame(
"echo '1 2 3 4 5 echo foo\n2 3 4 5 6 echo bar' | 'crontab' '-u' 'admin'",
$server = Server::via(
function($command) {
$this->assertSame(
"echo '1 2 3 4 5 echo foo\n2 3 4 5 6 echo bar' | crontab '-u' 'admin'",
$command->toString(),
),
);
);

return Attempt::result(Builder::foreground(2)->build());
},
);

$this->assertInstanceOf(SideEffect::class, $crontab($server)->unwrap());
}
Expand All @@ -83,11 +101,13 @@ public function testReturnErrorWhenInstallFailed()
Job::of('1 2 3 4 5 echo foo'),
Job::of('2 3 4 5 6 echo bar'),
);
$server = Mock::new($this->assert())
->willExecute(
static fn() => null,
static fn($_, $builder) => $builder->failed(),
);
$server = Server::via(
static fn() => Attempt::result(
Builder::foreground(2)
->failed()
->build(),
),
);

$error = $crontab($server)->match(
static fn() => null,
Expand Down
136 changes: 82 additions & 54 deletions tests/ReadTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,43 +4,55 @@
namespace Tests\Innmind\Cron;

use Innmind\Cron\Read;
use Innmind\Server\Control\Servers\Mock;
use Innmind\Immutable\Sequence;
use Innmind\Server\Control\{
Server,
Server\Process\Builder,
};
use Innmind\Immutable\{
Sequence,
Attempt,
};
use Innmind\BlackBox\PHPUnit\Framework\TestCase;

class ReadTest extends TestCase
{
public function testReadCrontabForConnectedUser()
{
$read = Read::forConnectedUser();
$server = Mock::new($this->assert())
->willExecute(
fn($command) => $this->assertSame(
$server = Server::via(
function($command) {
$this->assertSame(
"crontab '-l'",
$command->toString(),
),
static fn($_, $builder) => $builder->success([
[
<<<CRONTAB
# First section
1 2 3 4 5 echo foo

# Second section
2 3 4 5 6 echo bar

CRONTAB,
'output',
],
]),
);
);

return Attempt::result(
Builder::foreground(2)
->success([
[
<<<CRONTAB
# First section
1 2 3 4 5 echo foo

# Second section
2 3 4 5 6 echo bar

CRONTAB,
'output',
],
])
->build(),
);
},
);

$jobs = $read($server)->match(
static fn($jobs) => $jobs,
static fn() => null,
);

$this->assertInstanceOf(Sequence::class, $jobs);
$this->assertCount(2, $jobs);
$this->assertSame(2, $jobs->size());
$this->assertSame('1 2 3 4 5 echo foo', $jobs->first()->match(
static fn($job) => $job->toString(),
static fn() => null,
Expand All @@ -54,34 +66,40 @@ public function testReadCrontabForConnectedUser()
public function testReadCrontabForSpecificUser()
{
$read = Read::forUser('admin');
$server = Mock::new($this->assert())
->willExecute(
fn($command) => $this->assertSame(
$server = Server::via(
function($command) {
$this->assertSame(
"crontab '-u' 'admin' '-l'",
$command->toString(),
),
static fn($_, $builder) => $builder->success([
[
<<<CRONTAB
# First section
1 2 3 4 5 echo foo

# Second section
2 3 4 5 6 echo bar

CRONTAB,
'output',
],
]),
);
);

return Attempt::result(
Builder::foreground(2)
->success([
[
<<<CRONTAB
# First section
1 2 3 4 5 echo foo

# Second section
2 3 4 5 6 echo bar

CRONTAB,
'output',
],
])
->build(),
);
},
);

$jobs = $read($server)->match(
static fn($jobs) => $jobs,
static fn() => null,
);

$this->assertInstanceOf(Sequence::class, $jobs);
$this->assertCount(2, $jobs);
$this->assertSame(2, $jobs->size());
$this->assertSame('1 2 3 4 5 echo foo', $jobs->first()->match(
static fn($job) => $job->toString(),
static fn() => null,
Expand All @@ -95,16 +113,20 @@ public function testReadCrontabForSpecificUser()
public function testReturnNothingWhenCrontabContainsInvalidJobs()
{
$read = Read::forUser('admin');
$server = Mock::new($this->assert())
->willExecute(
fn($command) => $this->assertSame(
$server = Server::via(
function($command) {
$this->assertSame(
"crontab '-u' 'admin' '-l'",
$command->toString(),
),
static fn($_, $builder) => $builder->success([
['*', 'output'],
]),
);
);

return Attempt::result(
Builder::foreground(2)
->success([['*', 'output']])
->build(),
);
},
);

$this->assertNull($read($server)->match(
static fn($jobs) => $jobs,
Expand All @@ -115,14 +137,20 @@ public function testReturnNothingWhenCrontabContainsInvalidJobs()
public function testReturnNothingWhenProcessToReadTheCrontabFailed()
{
$read = Read::forUser('admin');
$server = Mock::new($this->assert())
->willExecute(
fn($command) => $this->assertSame(
$server = Server::via(
function($command) {
$this->assertSame(
"crontab '-u' 'admin' '-l'",
$command->toString(),
),
static fn($_, $builder) => $builder->failed(),
);
);

return Attempt::result(
Builder::foreground(2)
->failed()
->build(),
);
},
);

$this->assertNull($read($server)->match(
static fn($jobs) => $jobs,
Expand Down