Skip to content

Commit 205e9fc

Browse files
authored
Generate full Perl tests for simple-cipher (#535)
1 parent 908db1d commit 205e9fc

File tree

14 files changed

+342
-221
lines changed

14 files changed

+342
-221
lines changed

config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -566,7 +566,8 @@
566566
"practices": [],
567567
"prerequisites": [],
568568
"difficulty": 1,
569-
"topics": []
569+
"topics": [],
570+
"status": "beta"
570571
},
571572
{
572573
"slug": "simple-linked-list",

exercises/practice/simple-cipher/.meta/config.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@
99
],
1010
"files": {
1111
"solution": [
12-
"Cipher.pm"
12+
"SimpleCipher.pm"
1313
],
1414
"test": [
15-
"cipher.t"
15+
"simple-cipher.t"
1616
],
1717
"example": [
18-
".meta/solutions/Cipher.pm"
18+
".meta/solutions/SimpleCipher.pm"
1919
]
2020
},
2121
"blurb": "Implement a simple shift cipher like Caesar and a more secure substitution cipher.",

exercises/practice/simple-cipher/.meta/solutions/Cipher.pm

Lines changed: 0 additions & 60 deletions
This file was deleted.
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package SimpleCipher;
2+
3+
use Moo;
4+
use feature qw<say>;
5+
use experimental qw<signatures postderef postderef_qq>;
6+
7+
has key => (
8+
is => 'lazy',
9+
);
10+
11+
sub encode ( $self, $plaintext ) {
12+
my $key = $self->key;
13+
my $key_length = length $key;
14+
my $ciphertext = '';
15+
for my $i ( 0 .. length($plaintext) - 1 ) {
16+
my $char = substr( $plaintext, $i, 1 );
17+
my $key_char = substr( $key, $i % $key_length, 1 );
18+
my $shift = ord($key_char) - ord('a');
19+
my $new_char
20+
= chr( ( ord($char) - ord('a') + $shift ) % 26 + ord('a') );
21+
$ciphertext .= $new_char;
22+
}
23+
return $ciphertext;
24+
}
25+
26+
sub decode ( $self, $ciphertext ) {
27+
my $key = $self->key;
28+
my $key_length = length $key;
29+
my $plaintext = '';
30+
for my $i ( 0 .. length($ciphertext) - 1 ) {
31+
my $char = substr( $ciphertext, $i, 1 );
32+
my $key_char = substr( $key, $i % $key_length, 1 );
33+
my $shift = ord($key_char) - ord('a');
34+
my $new_char
35+
= chr( ( ord($char) - ord('a') - $shift + 26 ) % 26 + ord('a') );
36+
$plaintext .= $new_char;
37+
}
38+
return $plaintext;
39+
}
40+
41+
sub _build_key {
42+
return join '', map { ( 'a' .. 'z' )[ rand 26 ] } 1 .. 100;
43+
}
44+
45+
1;

exercises/practice/simple-cipher/.meta/solutions/cipher.t

Lines changed: 0 additions & 1 deletion
This file was deleted.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
requires 'Moo';
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../simple-cipher.t
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
methods: key encode decode
2+
moo: true
3+
tests: |
4+
my $cipher;
5+
properties:
6+
key:
7+
test: |-
8+
use Data::Dmp;
9+
sprintf(<<~'END', $case->{expected}{match}, dmp($case->{description}));
10+
$cipher = SimpleCipher->new;
11+
like(
12+
$cipher->key,
13+
qr/%s/,
14+
%s,
15+
);
16+
END
17+
18+
encode:
19+
test: |-
20+
use Data::Dmp;
21+
if ($case->{input}{key}) {
22+
sprintf(<<~'END', map {dmp($_)} @{$case->{input}}{qw<key plaintext>}, @{$case}{qw<expected description>});
23+
$cipher = SimpleCipher->new(key => %s);
24+
is(
25+
$cipher->encode(%s),
26+
%s,
27+
%s,
28+
);
29+
END
30+
}
31+
else {
32+
sprintf(<<~'END', dmp($case->{input}{plaintext}), length($case->{input}{plaintext}), dmp($case->{description}));
33+
$cipher = SimpleCipher->new;
34+
is(
35+
$cipher->encode(%s),
36+
substr( $cipher->key, 0, %u ),
37+
%s,
38+
);
39+
END
40+
}
41+
42+
decode:
43+
test: |-
44+
use Data::Dmp;
45+
if ($case->{input}{key}) {
46+
if ($case->{input}{plaintext}) {
47+
sprintf(<<~'END', map {dmp($_)} @{$case->{input}}{qw<key plaintext>}, @{$case}{qw<expected description>});
48+
$cipher = SimpleCipher->new( key => %s );
49+
is(
50+
$cipher->decode($cipher->encode(%s)),
51+
%s,
52+
%s,
53+
);
54+
END
55+
}
56+
else {
57+
sprintf(<<~'END', map {dmp($_)} @{$case->{input}}{qw<key ciphertext>}, @{$case}{qw<expected description>});
58+
$cipher = SimpleCipher->new( key => %s );
59+
is(
60+
$cipher->decode(%s),
61+
%s,
62+
%s,
63+
);
64+
END
65+
}
66+
}
67+
elsif ($case->{input}{plaintext}) {
68+
sprintf(<<~'END', map {dmp($_)} $case->{input}{plaintext}, @{$case}{qw<expected description>});
69+
$cipher = SimpleCipher->new;
70+
is(
71+
$cipher->decode($cipher->encode(%s)),
72+
%s,
73+
%s,
74+
);
75+
END
76+
}
77+
else {
78+
sprintf(<<~'END', length($case->{expected}), map {dmp($_)} @{$case}{qw<expected description>});
79+
$cipher = SimpleCipher->new;
80+
is(
81+
$cipher->decode( substr( $cipher->key, 0, %u ) ),
82+
%s,
83+
%s,
84+
);
85+
END
86+
}
87+
88+
example: |-
89+
has key => (
90+
is => 'lazy',
91+
);
92+
93+
sub encode ($self, $plaintext) {
94+
my $key = $self->key;
95+
my $key_length = length $key;
96+
my $ciphertext = '';
97+
for my $i (0..length($plaintext)-1) {
98+
my $char = substr($plaintext, $i, 1);
99+
my $key_char = substr($key, $i % $key_length, 1);
100+
my $shift = ord($key_char) - ord('a');
101+
my $new_char = chr((ord($char) - ord('a') + $shift) % 26 + ord('a'));
102+
$ciphertext .= $new_char;
103+
}
104+
return $ciphertext;
105+
}
106+
107+
sub decode ($self, $ciphertext) {
108+
my $key = $self->key;
109+
my $key_length = length $key;
110+
my $plaintext = '';
111+
for my $i (0..length($ciphertext)-1) {
112+
my $char = substr($ciphertext, $i, 1);
113+
my $key_char = substr($key, $i % $key_length, 1);
114+
my $shift = ord($key_char) - ord('a');
115+
my $new_char = chr((ord($char) - ord('a') - $shift + 26) % 26 + ord('a'));
116+
$plaintext .= $new_char;
117+
}
118+
return $plaintext;
119+
}
120+
121+
sub _build_key {
122+
return join '', map { ('a'..'z')[rand 26] } 1..100;
123+
}
124+
125+
stub: |-
126+
has key => (
127+
is => 'lazy',
128+
);
129+
130+
sub encode {
131+
my ($self) = @_;
132+
return undef;
133+
}
134+
135+
sub decode {
136+
my ($self) = @_;
137+
return undef;
138+
}
139+
140+
sub _build_key {
141+
return undef;
142+
}
Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,46 @@
1-
# This is an auto-generated file. Regular comments will be removed when this
2-
# file is regenerated. Regenerating will not touch any manually added keys,
3-
# so comments can be added in a "comment" key.
1+
# This is an auto-generated file.
2+
#
3+
# Regenerating this file via `configlet sync` will:
4+
# - Recreate every `description` key/value pair
5+
# - Recreate every `reimplements` key/value pair, where they exist in problem-specifications
6+
# - Remove any `include = true` key/value pair (an omitted `include` key implies inclusion)
7+
# - Preserve any other key/value pair
8+
#
9+
# As user-added comments (using the # character) will be removed when this file
10+
# is regenerated, comments can be added via a `comment` key.
411

512
[b8bdfbe1-bea3-41bb-a999-b41403f2b15d]
6-
description = "Can encode"
13+
description = "Random key cipher -> Can encode"
714

815
[3dff7f36-75db-46b4-ab70-644b3f38b81c]
9-
description = "Can decode"
16+
description = "Random key cipher -> Can decode"
1017

1118
[8143c684-6df6-46ba-bd1f-dea8fcb5d265]
12-
description = "Is reversible. I.e., if you apply decode in a encoded result, you must see the same plaintext encode parameter as a result of the decode method"
19+
description = "Random key cipher -> Is reversible. I.e., if you apply decode in a encoded result, you must see the same plaintext encode parameter as a result of the decode method"
1320

1421
[defc0050-e87d-4840-85e4-51a1ab9dd6aa]
15-
description = "Key is made only of lowercase letters"
22+
description = "Random key cipher -> Key is made only of lowercase letters"
1623

1724
[565e5158-5b3b-41dd-b99d-33b9f413c39f]
18-
description = "Can encode"
25+
description = "Substitution cipher -> Can encode"
1926

2027
[d44e4f6a-b8af-4e90-9d08-fd407e31e67b]
21-
description = "Can decode"
28+
description = "Substitution cipher -> Can decode"
2229

2330
[70a16473-7339-43df-902d-93408c69e9d1]
24-
description = "Is reversible. I.e., if you apply decode in a encoded result, you must see the same plaintext encode parameter as a result of the decode method"
31+
description = "Substitution cipher -> Is reversible. I.e., if you apply decode in a encoded result, you must see the same plaintext encode parameter as a result of the decode method"
2532

2633
[69a1458b-92a6-433a-a02d-7beac3ea91f9]
27-
description = "Can double shift encode"
34+
description = "Substitution cipher -> Can double shift encode"
2835

2936
[21d207c1-98de-40aa-994f-86197ae230fb]
30-
description = "Can wrap on encode"
37+
description = "Substitution cipher -> Can wrap on encode"
3138

3239
[a3d7a4d7-24a9-4de6-bdc4-a6614ced0cb3]
33-
description = "Can wrap on decode"
40+
description = "Substitution cipher -> Can wrap on decode"
3441

3542
[e31c9b8c-8eb6-45c9-a4b5-8344a36b9641]
36-
description = "Can encode messages longer than the key"
43+
description = "Substitution cipher -> Can encode messages longer than the key"
3744

3845
[93cfaae0-17da-4627-9a04-d6d1e1be52e3]
39-
description = "Can decode messages longer than the key"
46+
description = "Substitution cipher -> Can decode messages longer than the key"

exercises/practice/simple-cipher/Cipher.pm

Lines changed: 0 additions & 24 deletions
This file was deleted.

0 commit comments

Comments
 (0)