lorca 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ChangeLog.md +38 -0
- data/License.md +13 -0
- data/Manifest.md +45 -0
- data/ReadMe.md +41 -0
- data/_expand_lib_path.rb +5 -0
- data/bin/lorca +9 -0
- data/bin/lorca-alpine +9 -0
- data/lib/lorca/doc.rb +42 -0
- data/lib/lorca/expansions/cli.rb +66 -0
- data/lib/lorca/expansions/phrases/eff_large_wordlist.dir +0 -0
- data/lib/lorca/expansions/phrases/eff_large_wordlist.pag +0 -0
- data/lib/lorca/expansions/phrases.rb +64 -0
- data/lib/lorca/manifest.rb +72 -0
- data/lib/lorca/version.rb +16 -0
- data/lib/lorca.rb +113 -0
- data/test/_config/minitest.rb +19 -0
- data/test/bin/test_lorca.rb +25 -0
- data/test/lib/lorca/expansions/test_cli.rb +59 -0
- data/test/lib/lorca/expansions/test_phrases.rb +66 -0
- data/test/lib/lorca/test_doc.rb +32 -0
- data/test/lib/lorca/test_manifest.rb +86 -0
- data/test/lib/lorca/test_version.rb +11 -0
- data/test/lib/test_lorca.rb +157 -0
- metadata +246 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: ab5b9ef8040a51c71e968398dc37c1e656cfb50246eb5d576b3565959f5a2f1c
|
|
4
|
+
data.tar.gz: 86fd64feae9c99878f0d1053f78a1ee2dd399831946f2436b9d4d29f8c590a0a
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: ef2adcc3d3fc5c3506e31132aaefe545bd79f4f504be6bab1434d5b15ad73a253fdc3caf37b8697d1a563b520a703a1245467078f5bb70ad673d18ffc78bbc63
|
|
7
|
+
data.tar.gz: df0ff349f468f3a310842f5ed37546d5c366138b68c43aafecd2c3ed4010fa22a9d76be5f40023a98270f76625d544f97b01ca0906fbe3a4bef50a30520821dd
|
data/ChangeLog.md
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# ChangeLog
|
|
2
|
+
|
|
3
|
+
## [Unreleased]
|
|
4
|
+
|
|
5
|
+
## [0.3.0]
|
|
6
|
+
|
|
7
|
+
### Security
|
|
8
|
+
|
|
9
|
+
- Use `Sysrandom` gem as pseudo-random generator for Ruby versions below 2.5.
|
|
10
|
+
|
|
11
|
+
### Added
|
|
12
|
+
|
|
13
|
+
- Lorca expansion system.
|
|
14
|
+
- LorcaCore expansion with base instance, and class, methods.
|
|
15
|
+
- Phrases expansion to generate passphrases. Based on EFF's diceware.
|
|
16
|
+
- CLI expansion to use Lorca from the terminal.
|
|
17
|
+
|
|
18
|
+
## [0.0.1]
|
|
19
|
+
|
|
20
|
+
### Security
|
|
21
|
+
|
|
22
|
+
- Added Manifest for everyone to keep track of gem files. Manually edited.
|
|
23
|
+
|
|
24
|
+
### Changed
|
|
25
|
+
|
|
26
|
+
- Extracted gemspec info to added modules.
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- Lorca::LorcaDoc, and Lorca::LorcaManifest modules.
|
|
31
|
+
- License.
|
|
32
|
+
- ChangeLog for users to keep track of relevant gem changes.
|
|
33
|
+
|
|
34
|
+
## [0.0.0]
|
|
35
|
+
|
|
36
|
+
### Added
|
|
37
|
+
|
|
38
|
+
- Lorca gemspec with bare minimum of files, and settings.
|
data/License.md
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Copyright (c) 2018, René Maya.
|
|
2
|
+
|
|
3
|
+
Permission to use, copy, modify, and distribute this software for any
|
|
4
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
5
|
+
copyright notice and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
8
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
9
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
10
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
11
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
12
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
|
13
|
+
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
data/Manifest.md
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
ChangeLog.md
|
|
2
|
+
|
|
3
|
+
License.md
|
|
4
|
+
|
|
5
|
+
Manifest.md
|
|
6
|
+
|
|
7
|
+
ReadMe.md
|
|
8
|
+
|
|
9
|
+
_expand_lib_path.rb
|
|
10
|
+
|
|
11
|
+
bin/lorca
|
|
12
|
+
|
|
13
|
+
bin/lorca-alpine
|
|
14
|
+
|
|
15
|
+
lib/lorca/doc.rb
|
|
16
|
+
|
|
17
|
+
lib/lorca/manifest.rb
|
|
18
|
+
|
|
19
|
+
lib/lorca/expansions/cli.rb
|
|
20
|
+
|
|
21
|
+
lib/lorca/expansions/phrases/eff_large_wordlist.dir
|
|
22
|
+
|
|
23
|
+
lib/lorca/expansions/phrases/eff_large_wordlist.pag
|
|
24
|
+
|
|
25
|
+
lib/lorca/expansions/phrases.rb
|
|
26
|
+
|
|
27
|
+
lib/lorca/version.rb
|
|
28
|
+
|
|
29
|
+
lib/lorca.rb
|
|
30
|
+
|
|
31
|
+
test/_config/minitest.rb
|
|
32
|
+
|
|
33
|
+
test/bin/test_lorca.rb
|
|
34
|
+
|
|
35
|
+
test/lib/test_lorca.rb
|
|
36
|
+
|
|
37
|
+
test/lib/lorca/expansions/test_cli.rb
|
|
38
|
+
|
|
39
|
+
test/lib/lorca/expansions/test_phrases.rb
|
|
40
|
+
|
|
41
|
+
test/lib/lorca/test_doc.rb
|
|
42
|
+
|
|
43
|
+
test/lib/lorca/test_manifest.rb
|
|
44
|
+
|
|
45
|
+
test/lib/lorca/test_version.rb
|
data/ReadMe.md
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Lorca
|
|
2
|
+
|
|
3
|
+
## Details
|
|
4
|
+
|
|
5
|
+
Lorca generates passphrases based on the algorithm originally described in
|
|
6
|
+
[EFF Dice-Generated Passphrases](https://www.eff.org/dice).
|
|
7
|
+
It uses [EFF's long word list](https://www.eff.org/files/2016/07/18/eff_large_wordlist.txt).
|
|
8
|
+
|
|
9
|
+
## System Requirements
|
|
10
|
+
|
|
11
|
+
- *nix OS.
|
|
12
|
+
- Ruby 2.4+
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Add to a project's Gemfile:
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
gem "lorca"
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
And then run
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
$ bundle
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or to install the command line interface locally:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
$ gem install lorca
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Quick Start
|
|
35
|
+
|
|
36
|
+
:TODO: Add usage examples here.
|
|
37
|
+
|
|
38
|
+
## License
|
|
39
|
+
|
|
40
|
+
Copyright (c) 2018, René Maya. Licensed ISC. Read attached `License.md` file
|
|
41
|
+
for details.
|
data/_expand_lib_path.rb
ADDED
data/bin/lorca
ADDED
data/bin/lorca-alpine
ADDED
data/lib/lorca/doc.rb
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
require "lorca/manifest"
|
|
4
|
+
|
|
5
|
+
class Lorca
|
|
6
|
+
# Aimed at gemspec, and supported doc generators.
|
|
7
|
+
module LorcaDoc
|
|
8
|
+
# One line summary of what Lorca is.
|
|
9
|
+
def self.summary
|
|
10
|
+
"Passphrase, and password generator"
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# Short description of what Lorca does, and how does it do it.
|
|
14
|
+
def self.description
|
|
15
|
+
<<~EOH
|
|
16
|
+
Lorca is a passphrase generator based on diceware made available by the EFF.
|
|
17
|
+
Passwords, and pins are handle by the system's pseudo-random generator.
|
|
18
|
+
EOH
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Array of options used for building the documentation.
|
|
22
|
+
def self.build_options
|
|
23
|
+
[
|
|
24
|
+
"--line-numbers",
|
|
25
|
+
"--title", "#{LorcaManifest.official_name}: #{self.summary}",
|
|
26
|
+
"--main", "ReadMe.md"
|
|
27
|
+
]
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Array of documented files. These should be listed in Manifest.md.
|
|
31
|
+
def self.files
|
|
32
|
+
Lorca::LorcaManifest.files.select { |f|
|
|
33
|
+
Lorca::LorcaManifest.codebase.any? { |dir| f.start_with? dir }
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Array of extra doc files. These should be listed in Manifest.md.
|
|
38
|
+
def self.appendices
|
|
39
|
+
Lorca::LorcaManifest.files.select { |f| f.end_with? ".md" }
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
|
|
4
|
+
require "optparse"
|
|
5
|
+
require "clipboard"
|
|
6
|
+
require "lorca/expansions/phrases"
|
|
7
|
+
|
|
8
|
+
class Lorca
|
|
9
|
+
module CLI # :nodoc:
|
|
10
|
+
|
|
11
|
+
# The CLI plugin enables Lorca use through the command line. It autoloads
|
|
12
|
+
# included plugins.
|
|
13
|
+
module LorcaPlugin
|
|
14
|
+
# Run Lorca with +options+ enabled.
|
|
15
|
+
# lorca = Lorca.plugin(Lorca::CLI).new
|
|
16
|
+
# lorca.run
|
|
17
|
+
def run options=$argv
|
|
18
|
+
cli_parse options
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
private
|
|
22
|
+
|
|
23
|
+
def cli_parse options
|
|
24
|
+
Object.new.extend(CLI).parse options
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.load_dependencies expansion, **_
|
|
29
|
+
expansion.add Lorca::Phrases
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def parse argv=$argv, writer:Lorca.new, pad: Clipboard, notice: $stdout
|
|
33
|
+
cli = OptionParser.new do |parser|
|
|
34
|
+
write_phrase parser, notice, writer, pad
|
|
35
|
+
display_help parser, notice
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
cli.parse!(*argv)
|
|
39
|
+
|
|
40
|
+
notice.puts cli
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
44
|
+
|
|
45
|
+
def write_phrase cli, notice, writer, pad
|
|
46
|
+
description = "Generate a passphrase with optional number of WORDS"
|
|
47
|
+
cli.on("-p", "--phrase [WORDS]", Integer, description) { |nw|
|
|
48
|
+
phrase = nw ? writer.phrase(words: nw) : writer.phrase
|
|
49
|
+
pad.copy phrase
|
|
50
|
+
notice.puts "passphrase copied to clipboard"
|
|
51
|
+
exit_cli
|
|
52
|
+
}
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def display_help cli, notice
|
|
56
|
+
cli.on_tail("-h", "--help", "Show this message") {
|
|
57
|
+
notice.puts cli
|
|
58
|
+
exit_cli
|
|
59
|
+
}
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def exit_cli status: 0
|
|
63
|
+
exit status unless ENV["LORCA_ENV"] == "test"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
require "sdbm"
|
|
4
|
+
|
|
5
|
+
class Lorca
|
|
6
|
+
# Built-in Phrases expansion. Adds all necessary dependencies to enable secure
|
|
7
|
+
# random phrases. Intended as a passphrase generator.
|
|
8
|
+
#
|
|
9
|
+
# It exposes the following instance methods:
|
|
10
|
+
#
|
|
11
|
+
# phrase :: A phrase randomly generated suitable as a passphrase.
|
|
12
|
+
module Phrases
|
|
13
|
+
# Default minimum number of words a user can request per phrase.
|
|
14
|
+
MIN_WORDS = 8.freeze
|
|
15
|
+
# Default maximum number of words a user can request per phrase.
|
|
16
|
+
MAX_WORDS = 53.freeze
|
|
17
|
+
# Default number of dice used for rolling a word id. Meant to fit the included
|
|
18
|
+
# vocabulary.
|
|
19
|
+
DICE = 5.freeze
|
|
20
|
+
# The default vocabulary's database path.
|
|
21
|
+
VOCABULARY = "./lib/lorca/expansions/phrases/eff_large_wordlist"
|
|
22
|
+
|
|
23
|
+
# Configure the Lorca::Phrases expansion upon loading.
|
|
24
|
+
#
|
|
25
|
+
# The following settings are configurable.
|
|
26
|
+
#
|
|
27
|
+
# min_words :: The minimum number of words a user can request per phrase.
|
|
28
|
+
# max_words :: The maximum number of words a user can request per phrase.
|
|
29
|
+
# dice_to_toss :: The number of dice to toss to generate a word id. It should
|
|
30
|
+
# only be changed when switching vocabulary.
|
|
31
|
+
# vocabulary :: The path to the SDBM compatible vocabulary database.
|
|
32
|
+
def self.configure expansion, min_words: MIN_WORDS, max_words: MAX_WORDS,
|
|
33
|
+
dice_to_toss: DICE, vocabulary: VOCABULARY
|
|
34
|
+
config = expansion.settings[:phrases] = {}
|
|
35
|
+
config[:min_words] = min_words
|
|
36
|
+
config[:max_words] = max_words
|
|
37
|
+
config[:dice_to_toss] = dice_to_toss
|
|
38
|
+
config[:vocabulary] = vocabulary
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
module LorcaPlugin
|
|
42
|
+
# The phrase written given a number of +words+.
|
|
43
|
+
def phrase words: settings[:phrases][:min_words]
|
|
44
|
+
conf = settings[:phrases]
|
|
45
|
+
words = validate_counter words, range: conf[:min_words]..conf[:max_words]
|
|
46
|
+
phrase_ids = []
|
|
47
|
+
words.times { phrase_ids.push(roll_word_id dice: conf[:dice_to_toss]) }
|
|
48
|
+
phrase_ids.map(&method(:word)).join " "
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# :nodoc:
|
|
52
|
+
private
|
|
53
|
+
|
|
54
|
+
WordIdError = Class.new StandardError
|
|
55
|
+
|
|
56
|
+
def word id, wordlist: settings[:phrases][:vocabulary], manager: SDBM
|
|
57
|
+
read_only = 0444
|
|
58
|
+
manager.open(wordlist, read_only) { |db| db.fetch id }
|
|
59
|
+
rescue => e
|
|
60
|
+
raise WordIdError, e.message
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
|
|
4
|
+
class Lorca
|
|
5
|
+
# Aimed at basic security auditing tools.
|
|
6
|
+
module LorcaManifest
|
|
7
|
+
# Name as used in `require` statements.
|
|
8
|
+
def self.gem_name
|
|
9
|
+
official_name.downcase
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Name as it's meant to be spelled.
|
|
13
|
+
def self.official_name
|
|
14
|
+
"Lorca"
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
# Array of authors' string names
|
|
18
|
+
def self.authors
|
|
19
|
+
["René Maya"].freeze
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
# Array of maintainers' email strings.
|
|
23
|
+
def self.contact_emails
|
|
24
|
+
%w[rem@disroot.org].freeze
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Main repo url.
|
|
28
|
+
def self.repo
|
|
29
|
+
"https://notabug.org/rem/lorca"
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# License type. Full text in License.md.
|
|
33
|
+
def self.license
|
|
34
|
+
"ISC"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Array of official gem files. Manually maintained at Manifest.md.
|
|
38
|
+
#--
|
|
39
|
+
# Not frozen, raises warnings building gem.
|
|
40
|
+
#++
|
|
41
|
+
def self.files
|
|
42
|
+
File.readlines("./Manifest.md").map(&:chomp).reject(&:empty?)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Array of directories housing the codebase.
|
|
46
|
+
def self.codebase
|
|
47
|
+
src = "lib"
|
|
48
|
+
[src].freeze if files.any? { |f| f.start_with? "#{src}/" }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Directory housing the test suite.
|
|
52
|
+
def self.test_suite
|
|
53
|
+
"test"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Array of test files.
|
|
57
|
+
def self.tests
|
|
58
|
+
tests = Dir["test/**/test_*.rb"] - Dir["test/dev/**/*.rb"]
|
|
59
|
+
tests.freeze
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Directory housing binstubs.
|
|
63
|
+
def self.bindir
|
|
64
|
+
"bin"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Array of binstubs.
|
|
68
|
+
def self.binstubs
|
|
69
|
+
%w[lorca].freeze
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
|
|
4
|
+
class Lorca
|
|
5
|
+
# Major version. Updated for changes that may require users to modify their code.
|
|
6
|
+
LorcaMajorVersion = 0
|
|
7
|
+
|
|
8
|
+
# Minor version. Updated for new feature releases.
|
|
9
|
+
LorcaMinorVersion = 3
|
|
10
|
+
|
|
11
|
+
# Patch version. Updated only for bug fixes from the last feature release.
|
|
12
|
+
LorcaPatchVersion = 0
|
|
13
|
+
|
|
14
|
+
# Full version as a string.
|
|
15
|
+
LorcaVersion = "#{LorcaMajorVersion}.#{LorcaMinorVersion}.#{LorcaPatchVersion}"
|
|
16
|
+
end
|
data/lib/lorca.rb
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
require "lorca/version"
|
|
4
|
+
|
|
5
|
+
begin
|
|
6
|
+
gem "sysrandom"
|
|
7
|
+
require "sysrandom/securerandom"
|
|
8
|
+
rescue Gem::LoadError
|
|
9
|
+
require "securerandom"
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
# Lorca main class.
|
|
13
|
+
class Lorca
|
|
14
|
+
# Exception raised by an invalid number of dice
|
|
15
|
+
LorcaDiceError = Class.new StandardError
|
|
16
|
+
|
|
17
|
+
# Exception raised by an invalid range
|
|
18
|
+
LorcaRangeError = Class.new StandardError
|
|
19
|
+
|
|
20
|
+
# Exception raised by an invalid counter
|
|
21
|
+
LorcaCounterError = Class.new StandardError
|
|
22
|
+
|
|
23
|
+
@settings = {}
|
|
24
|
+
|
|
25
|
+
# Lorca core methods.
|
|
26
|
+
module LorcaCore
|
|
27
|
+
# LorcaCore class methods.
|
|
28
|
+
module LorcaExtension
|
|
29
|
+
class << self
|
|
30
|
+
# Expose warn as it is used for deprecation warnings.
|
|
31
|
+
# Lorca::LorcaCore::LorcaExtension.warn can be overridden for custom
|
|
32
|
+
# extension warnings.
|
|
33
|
+
public :warn
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Lorca class settings/configuration hash.
|
|
37
|
+
attr_reader :settings
|
|
38
|
+
|
|
39
|
+
# Adds a Lorca Expansion. An expansion is simply a module which changes
|
|
40
|
+
# Lorca. Methods defined under the +ExpansionName::LorcaPlugin+ namespace
|
|
41
|
+
# get included. The ones defined under +ExpansionName::LorcaExtension+,
|
|
42
|
+
# extended.
|
|
43
|
+
#
|
|
44
|
+
# Expansions can define +ExpansionName.load_dependencies+ to load, and
|
|
45
|
+
# configure their dependencies. They can also define +ExpansionName.configure+
|
|
46
|
+
# so users can modify its settings.
|
|
47
|
+
#--
|
|
48
|
+
# don't load from load_path; security over convenience
|
|
49
|
+
# rename add
|
|
50
|
+
#++
|
|
51
|
+
def add expansion, **stns, &block
|
|
52
|
+
expansion.load_dependencies(self, **stns, &block) if expansion.respond_to?(:load_dependencies)
|
|
53
|
+
include expansion::LorcaPlugin if defined? expansion::LorcaPlugin
|
|
54
|
+
extend expansion::LorcaExtension if defined? expansion::LorcaExtension
|
|
55
|
+
expansion.configure(self, **stns, &block) if expansion.respond_to?(:configure)
|
|
56
|
+
self
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# LorcaCore instance methods.
|
|
61
|
+
module LorcaPlugin
|
|
62
|
+
# Lorca instance settings hash. Frozen duplicate of class settings meant
|
|
63
|
+
# for reading expansion configurations.
|
|
64
|
+
def settings
|
|
65
|
+
self.class.settings.dup.freeze
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# Roll a word id using given number of +dice+.
|
|
69
|
+
def roll_word_id(dice:)
|
|
70
|
+
dice = validate_counter dice, range: dice..dice
|
|
71
|
+
id = ""
|
|
72
|
+
dice.times { id += roll_dice.to_s }
|
|
73
|
+
id
|
|
74
|
+
rescue Lorca::LorcaCounterError => e
|
|
75
|
+
raise Lorca::LorcaDiceError, e.message
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Roll a six-sided dice.
|
|
79
|
+
def roll_dice
|
|
80
|
+
(SecureRandom.random_number(5) + 1)
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
# Validate a given counter +number+ is within the given +range+.
|
|
84
|
+
def validate_counter(number, range:)
|
|
85
|
+
num = validate_positive_integer number
|
|
86
|
+
return num if num == range.min && num == range.max
|
|
87
|
+
|
|
88
|
+
range = validate_range range
|
|
89
|
+
range.cover?(num) ? num : fail(LorcaCounterError, "Counter out of range")
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
# Validate the +range+ given is end-inclusive, and only positive numbers.
|
|
93
|
+
def validate_range range
|
|
94
|
+
validate_positive_integer range.min
|
|
95
|
+
validate_positive_integer range.max
|
|
96
|
+
range
|
|
97
|
+
rescue Lorca::LorcaCounterError
|
|
98
|
+
raise LorcaRangeError, "Should be an end-inclusive range of positive integers"
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Validate +counter+ is a number greater than zero.
|
|
102
|
+
def validate_positive_integer counter
|
|
103
|
+
unless counter.is_a?(Integer) && counter > 0
|
|
104
|
+
fail LorcaCounterError, "Should be a positive integer"
|
|
105
|
+
end
|
|
106
|
+
counter
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
extend LorcaCore::LorcaExtension
|
|
112
|
+
add LorcaCore
|
|
113
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
|
|
4
|
+
require "minitest/autorun"
|
|
5
|
+
require "minitest/pride"
|
|
6
|
+
require "minitest/proveit"
|
|
7
|
+
require "minitest/unordered"
|
|
8
|
+
require_relative "./../../_expand_lib_path"
|
|
9
|
+
|
|
10
|
+
class Minitest::Test
|
|
11
|
+
make_my_diffs_pretty!
|
|
12
|
+
prove_it!
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
module Minitest::Assertions
|
|
16
|
+
def assert_frozen obj
|
|
17
|
+
assert obj.frozen?, "Expected #{obj.inspect} to be frozen"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
|
|
4
|
+
require "_config/minitest"
|
|
5
|
+
require "rbconfig"
|
|
6
|
+
|
|
7
|
+
class TestLorcaBin < Minitest::Test
|
|
8
|
+
def test_binstubs_return_usage_by_default
|
|
9
|
+
skip "slow CLI Integration" unless ENV["LORCA_ALL_TESTS"]
|
|
10
|
+
|
|
11
|
+
host = RbConfig::CONFIG["host_vendor"]
|
|
12
|
+
lorca = "lorca"
|
|
13
|
+
lorca += %r"alpine".match?(host) ? "-#{host}" : ""
|
|
14
|
+
|
|
15
|
+
out, _ = capture_subprocess_io { system lorca }
|
|
16
|
+
assert_match %r"usage:"i, out
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_binstubs_permissions
|
|
20
|
+
lorca = "bin/lorca"
|
|
21
|
+
|
|
22
|
+
assert File.executable_real? lorca
|
|
23
|
+
assert File.executable_real? "#{lorca}-alpine"
|
|
24
|
+
end
|
|
25
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
require_relative "./../../../_config/minitest"
|
|
4
|
+
require "lorca/expansions/cli"
|
|
5
|
+
|
|
6
|
+
class TestLorcaCLIExpansion < Minitest::Test
|
|
7
|
+
|
|
8
|
+
# test dependencies, useful for testing Lorca::CLI but should be replaceable
|
|
9
|
+
require "lorca"
|
|
10
|
+
require "clipboard" # Lorca can't paste, nor clear, clipboard contents
|
|
11
|
+
|
|
12
|
+
def setup
|
|
13
|
+
@argv = -> options { Array[StringIO.new(options).read.split] }
|
|
14
|
+
@cli = Object.new.extend Lorca::CLI
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def test_display_help_when_no_options_given
|
|
18
|
+
assert_output(%r"\Ausage"i) { @cli.parse @argv.("") }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_h__help_shows_usage_info
|
|
22
|
+
assert_output(%r"\Ausage"i) { @cli.parse @argv.("-h") }
|
|
23
|
+
assert_output(%r"\Ausage"i) { @cli.parse @argv.("--help") }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def test_p__phrase_copies_passphrase_to_clipboard
|
|
27
|
+
writer = Lorca.add(Lorca::Phrases).new
|
|
28
|
+
message = %r"\Apassphrase copied to clipboard\n"i # no `\z` due to `exit_cli`
|
|
29
|
+
copied = "ah"
|
|
30
|
+
|
|
31
|
+
writer.stub :phrase, copied do
|
|
32
|
+
assert_output(message) { @cli.parse @argv.("--phrase"), writer: writer }
|
|
33
|
+
assert_output { @cli.parse @argv.("-p"), writer: writer }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
assert_equal copied, Clipboard.paste
|
|
37
|
+
Clipboard.clear
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_phrase_is_composed_of_as_many_words_as_the_given_number
|
|
41
|
+
writer = Lorca.add(Lorca::Phrases).new
|
|
42
|
+
copied = "ah"
|
|
43
|
+
|
|
44
|
+
writer.stub :phrase, copied do
|
|
45
|
+
_ = capture_io { @cli.parse @argv.("--phrase 9"), writer: writer }
|
|
46
|
+
assert_equal copied, Clipboard.paste
|
|
47
|
+
end
|
|
48
|
+
Clipboard.clear
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
class TestCLILorcaPlugin < Minitest::Test
|
|
53
|
+
def test_lorca_cli_plugin
|
|
54
|
+
argv = -> options { Array[StringIO.new(options).read.split] }
|
|
55
|
+
lorca = Lorca.add(Lorca::CLI).new
|
|
56
|
+
|
|
57
|
+
assert_output(%r"\Ausage"i) { lorca.run argv.("") }
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
require_relative "./../../../_config/minitest"
|
|
4
|
+
require "lorca"
|
|
5
|
+
require "lorca/expansions/phrases"
|
|
6
|
+
|
|
7
|
+
# Use stubs for built-in expansions. External ones should instanciate Lorca.
|
|
8
|
+
class TestLorcaPhrasesExpansion < Minitest::Test
|
|
9
|
+
def setup
|
|
10
|
+
Lorca.add Lorca::Phrases
|
|
11
|
+
@lorca = Lorca.new
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def test_returns_a_phrase_with_a_pre_set_length
|
|
15
|
+
@lorca.stub(:roll_word_id, "11111") do
|
|
16
|
+
assert_match %r"\A(abacus *){8}\z", @lorca.phrase
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_writes_a_phrase_which_words_matches_the_given_number
|
|
21
|
+
num = 10
|
|
22
|
+
|
|
23
|
+
@lorca.stub(:roll_word_id, "11111") do
|
|
24
|
+
assert_match %r/([a-z]+ *){#{num}}/, @lorca.phrase(words: num)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_fails_to_return_a_phrase_given_less_words_than_default
|
|
29
|
+
assert_raises(Lorca::LorcaCounterError) { @lorca.phrase words: 7 }
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def test_fails_to_return_a_phrase_given_an_invalid_amount_of_words
|
|
33
|
+
assert_raises(Lorca::LorcaCounterError) { @lorca.phrase words: Object.new }
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def test_configures_min_words
|
|
37
|
+
Lorca.add Lorca::Phrases, min_words: 9
|
|
38
|
+
|
|
39
|
+
assert_equal 9, Lorca.settings[:phrases][:min_words]
|
|
40
|
+
|
|
41
|
+
@lorca.stub(:roll_word_id, "11111") do
|
|
42
|
+
assert_match %r"\A(abacus *){9}\z", @lorca.phrase
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def test_configures_max_words
|
|
47
|
+
Lorca.add Lorca::Phrases, max_words: 12
|
|
48
|
+
|
|
49
|
+
assert_equal 12, Lorca.settings[:phrases][:max_words]
|
|
50
|
+
assert_raises { @lorca.phrase words: 13 }
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_configures_dice_to_toss_per_word_id
|
|
54
|
+
Lorca.add Lorca::Phrases, dice_to_toss: 3
|
|
55
|
+
|
|
56
|
+
assert_equal 3, Lorca.settings[:phrases][:dice_to_toss]
|
|
57
|
+
assert_raises { @lorca.phrase }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_configures_vocabulary
|
|
61
|
+
path = "path/to/non/existent/vocab"
|
|
62
|
+
Lorca.add Lorca::Phrases, vocabulary: path
|
|
63
|
+
assert_equal path, Lorca.settings[:phrases][:vocabulary]
|
|
64
|
+
assert_raises { @lorca.phrase }
|
|
65
|
+
end
|
|
66
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
|
|
4
|
+
require "_config/minitest"
|
|
5
|
+
require "lorca/doc"
|
|
6
|
+
|
|
7
|
+
# Tests w/ assert_respond_to show we care about the method existing not what's
|
|
8
|
+
# returned, nor it's type. The type is implicitly check by building a gem w/o
|
|
9
|
+
# warnings. There's a test for that.
|
|
10
|
+
class TestLorcaDoc < Minitest::Test
|
|
11
|
+
def test_has_summary
|
|
12
|
+
assert_respond_to Lorca::LorcaDoc, :summary
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_has_description
|
|
16
|
+
assert_respond_to Lorca::LorcaDoc, :description
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_has_build_options
|
|
20
|
+
assert_respond_to Lorca::LorcaDoc, :build_options
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_documented_files_are_listed_in_the_manifest
|
|
24
|
+
manifest = Lorca::LorcaManifest.files
|
|
25
|
+
Lorca::LorcaDoc.files.each { |f| assert_includes manifest, f }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_appendices_are_among_files_listed_in_the_manifest
|
|
29
|
+
manifest = Lorca::LorcaManifest.files
|
|
30
|
+
Lorca::LorcaDoc.appendices.each { |a| assert_includes manifest, a }
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
require_relative "./../../_config/minitest"
|
|
4
|
+
require "lorca/manifest"
|
|
5
|
+
|
|
6
|
+
class TestLorcaManifest < Minitest::Test
|
|
7
|
+
def test_has_gem_name
|
|
8
|
+
assert_equal "lorca", Lorca::LorcaManifest.gem_name
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def test_has_official_name
|
|
12
|
+
assert_equal "Lorca", Lorca::LorcaManifest.official_name
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def test_has_authors
|
|
16
|
+
expected_authors = ["René Maya"]
|
|
17
|
+
authors = Lorca::LorcaManifest.authors
|
|
18
|
+
|
|
19
|
+
assert_equal expected_authors, authors
|
|
20
|
+
assert_frozen authors
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def test_has_contact_emails
|
|
24
|
+
expected_emails = %w[rem@disroot.org]
|
|
25
|
+
emails = Lorca::LorcaManifest.contact_emails
|
|
26
|
+
assert_equal expected_emails, emails
|
|
27
|
+
assert_frozen emails
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_has_repo
|
|
31
|
+
assert_equal "https://notabug.org/rem/lorca", Lorca::LorcaManifest.repo
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def test_has_license
|
|
35
|
+
assert_equal "ISC", Lorca::LorcaManifest.license
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def test_has_files
|
|
39
|
+
# test/**/dev/**/*.* files are excluded because they are development helpers
|
|
40
|
+
expected_files =
|
|
41
|
+
%w[ChangeLog.md License.md Manifest.md ReadMe.md _expand_lib_path.rb] +
|
|
42
|
+
Dir["bin/*"] +
|
|
43
|
+
Dir["{lib,test}/**/*.{rb,txt,dir,pag}"] -
|
|
44
|
+
Dir["test/**/dev/**/*.{rb,txt}"]
|
|
45
|
+
|
|
46
|
+
# assert_frozen missing. Apparently Gem::Specification mutates it.
|
|
47
|
+
# must be unordered because CI
|
|
48
|
+
assert_equal_unordered expected_files, Lorca::LorcaManifest.files
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def test_codebase_returns_required_paths_basenames
|
|
52
|
+
lib = "lib"
|
|
53
|
+
codebase = Lorca::LorcaManifest.codebase
|
|
54
|
+
|
|
55
|
+
assert Lorca::LorcaManifest.files.any? { |f| %r[\A#{lib}/(.*)].match? f }
|
|
56
|
+
assert_equal [lib], codebase
|
|
57
|
+
assert_frozen codebase
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test__test_suite_returns_test_dir_basename
|
|
61
|
+
suite = "test"
|
|
62
|
+
assert_equal suite, Lorca::LorcaManifest.test_suite
|
|
63
|
+
assert Lorca::LorcaManifest.files.any? { |f| %r[\A#{suite}/(.*)].match? f }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test__tests_are_included_in_the_manifest
|
|
67
|
+
tests = Lorca::LorcaManifest.tests
|
|
68
|
+
files = Lorca::LorcaManifest.files
|
|
69
|
+
|
|
70
|
+
tests.each { |t| assert_includes files, t }
|
|
71
|
+
assert_frozen tests
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def test_has_bindir
|
|
75
|
+
assert_equal "bin", Lorca::LorcaManifest.bindir
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_binstubs_are_among_files_in_the_manifest
|
|
79
|
+
binstubs = Lorca::LorcaManifest.binstubs
|
|
80
|
+
files = Lorca::LorcaManifest.files
|
|
81
|
+
bindir = Lorca::LorcaManifest.bindir
|
|
82
|
+
|
|
83
|
+
binstubs.each { |b| assert_includes files, "#{bindir}/#{b}" }
|
|
84
|
+
assert_frozen binstubs
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
|
|
4
|
+
require "_config/minitest"
|
|
5
|
+
require "lorca/version"
|
|
6
|
+
|
|
7
|
+
class TestLorcaVersion < Minitest::Test
|
|
8
|
+
def test_lorca_has_a_version
|
|
9
|
+
assert_match %r{\d+.\d+.\d+}, Lorca::LorcaVersion
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# -*- frozen_string_literal: true -*-
|
|
3
|
+
require_relative "./../_config/minitest"
|
|
4
|
+
require "lorca"
|
|
5
|
+
|
|
6
|
+
module FakeExpansion
|
|
7
|
+
module LorcaPlugin
|
|
8
|
+
def fake
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module LorcaExtension
|
|
13
|
+
def warn msg="extension deprecation"
|
|
14
|
+
super msg
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
module NoPluginExpansion
|
|
20
|
+
LorcaExtension = Module.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
module NoExtensionExpansion
|
|
24
|
+
LorcaPlugin = Module.new
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module LoadsDependenciesExpansion
|
|
28
|
+
def self.load_dependencies mod, **_
|
|
29
|
+
mod.send(:include, Module.new {
|
|
30
|
+
def whatever
|
|
31
|
+
true
|
|
32
|
+
end
|
|
33
|
+
}
|
|
34
|
+
)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
module ConfigurableExpansion
|
|
39
|
+
def self.configure mod, **stns#, &block
|
|
40
|
+
mod.settings[:something] = stns[:something]
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
class TestLorcaCoreExtension < Minitest::Test
|
|
45
|
+
def test_lorca_can_add_expansions
|
|
46
|
+
Lorca.add FakeExpansion
|
|
47
|
+
lorca = Lorca.new
|
|
48
|
+
|
|
49
|
+
assert_respond_to lorca, :fake
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_extensions_can_override_warn_for_custom_warnings
|
|
53
|
+
Lorca.add FakeExpansion
|
|
54
|
+
_, warning = capture_io { Lorca.warn }
|
|
55
|
+
|
|
56
|
+
assert_match %r/extension deprecation/, warning
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def test_add_expansion_with_no_plugin
|
|
60
|
+
assert Lorca.add(NoPluginExpansion)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def test_add_expansion_with_no_extension
|
|
64
|
+
assert Lorca.add(NoExtensionExpansion)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def test_add_expansions_in_succession
|
|
68
|
+
assert Lorca.add(Module.new).add(Module.new)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def test_expansion_can_load_dependencies_when_needed
|
|
72
|
+
Lorca.add LoadsDependenciesExpansion
|
|
73
|
+
assert Lorca.new.whatever
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_can_configure_expansion_when_added
|
|
77
|
+
Lorca.add ConfigurableExpansion, something: "configured"
|
|
78
|
+
assert_equal "configured", Lorca.settings[:something]
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
class TestLorcaCorePlugin < Minitest::Test
|
|
83
|
+
def setup
|
|
84
|
+
@lorca = Lorca.new
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def test_has_immutable_settings
|
|
88
|
+
assert_frozen @lorca.settings
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_rolls_dice
|
|
92
|
+
assert_includes 1..6, @lorca.roll_dice
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def test_rolls_a_word_id_given_n_dice
|
|
96
|
+
n_dice = 5
|
|
97
|
+
assert_match %r/[1-6]{#{n_dice}}/, @lorca.roll_word_id(dice: n_dice)
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def test_fails_to_roll_word_id_given_invalid_number_of_dice
|
|
101
|
+
[0, -1, nil, Object.new].map do |invalid_dice|
|
|
102
|
+
e = assert_raises(Lorca::LorcaDiceError) {
|
|
103
|
+
@lorca.roll_word_id dice: invalid_dice
|
|
104
|
+
}
|
|
105
|
+
assert_match %r"should be a positive integer"i, e.message
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def test_validates_counter_is_within_range
|
|
110
|
+
num = 8
|
|
111
|
+
assert_equal num, @lorca.validate_counter(num, range: 1..10)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_fails_to_validate_counter_out_of_range
|
|
115
|
+
err_min = assert_raises(Lorca::LorcaCounterError) do
|
|
116
|
+
@lorca.validate_counter 3, range: 4..7
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
err_max = assert_raises(Lorca::LorcaCounterError) do
|
|
120
|
+
@lorca.validate_counter 8, range: 4..7
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
message = %r"\Acounter out of range\z"i
|
|
124
|
+
assert_match message, err_min.message
|
|
125
|
+
assert_match message, err_max.message
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def test_validates_a_range
|
|
129
|
+
range = 3..6
|
|
130
|
+
assert_equal range, @lorca.validate_range(range)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def test_fails_to_validate_an_invalid_range
|
|
134
|
+
[3..2, 4..0, -1..4, "a".."z"].map do |invalid_range|
|
|
135
|
+
e = assert_raises(Lorca::LorcaRangeError) {
|
|
136
|
+
@lorca.validate_range invalid_range
|
|
137
|
+
}
|
|
138
|
+
assert_match %r"\Ashould be an end-inclusive range of positive integers\z"i,
|
|
139
|
+
e.message
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def test_validates_positive_integer
|
|
144
|
+
num = 8
|
|
145
|
+
assert_equal num, @lorca.validate_positive_integer(num)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def test_fails_to_validate_positive_integer_given_invalid_input
|
|
149
|
+
[-1, 0, 2.1, Object.new, nil].map do |invalid_counter|
|
|
150
|
+
e = assert_raises(Lorca::LorcaCounterError) {
|
|
151
|
+
@lorca.validate_positive_integer invalid_counter
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
assert_match %r"\Ashould be a positive integer\z"i, e.message
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lorca
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.3.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- René Maya
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2018-05-04 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: clipboard
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - "~>"
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.1'
|
|
20
|
+
- - ">="
|
|
21
|
+
- !ruby/object:Gem::Version
|
|
22
|
+
version: 1.1.1
|
|
23
|
+
type: :runtime
|
|
24
|
+
prerelease: false
|
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
26
|
+
requirements:
|
|
27
|
+
- - "~>"
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '1.1'
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: 1.1.1
|
|
33
|
+
- !ruby/object:Gem::Dependency
|
|
34
|
+
name: bundler
|
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - "~>"
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '1.16'
|
|
40
|
+
- - ">="
|
|
41
|
+
- !ruby/object:Gem::Version
|
|
42
|
+
version: 1.16.1
|
|
43
|
+
type: :development
|
|
44
|
+
prerelease: false
|
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
46
|
+
requirements:
|
|
47
|
+
- - "~>"
|
|
48
|
+
- !ruby/object:Gem::Version
|
|
49
|
+
version: '1.16'
|
|
50
|
+
- - ">="
|
|
51
|
+
- !ruby/object:Gem::Version
|
|
52
|
+
version: 1.16.1
|
|
53
|
+
- !ruby/object:Gem::Dependency
|
|
54
|
+
name: rake
|
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
|
56
|
+
requirements:
|
|
57
|
+
- - "~>"
|
|
58
|
+
- !ruby/object:Gem::Version
|
|
59
|
+
version: '12.3'
|
|
60
|
+
- - ">="
|
|
61
|
+
- !ruby/object:Gem::Version
|
|
62
|
+
version: 12.3.0
|
|
63
|
+
type: :development
|
|
64
|
+
prerelease: false
|
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
66
|
+
requirements:
|
|
67
|
+
- - "~>"
|
|
68
|
+
- !ruby/object:Gem::Version
|
|
69
|
+
version: '12.3'
|
|
70
|
+
- - ">="
|
|
71
|
+
- !ruby/object:Gem::Version
|
|
72
|
+
version: 12.3.0
|
|
73
|
+
- !ruby/object:Gem::Dependency
|
|
74
|
+
name: hanna-nouveau
|
|
75
|
+
requirement: !ruby/object:Gem::Requirement
|
|
76
|
+
requirements:
|
|
77
|
+
- - "~>"
|
|
78
|
+
- !ruby/object:Gem::Version
|
|
79
|
+
version: '1.0'
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: 1.0.3
|
|
83
|
+
type: :development
|
|
84
|
+
prerelease: false
|
|
85
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - "~>"
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '1.0'
|
|
90
|
+
- - ">="
|
|
91
|
+
- !ruby/object:Gem::Version
|
|
92
|
+
version: 1.0.3
|
|
93
|
+
- !ruby/object:Gem::Dependency
|
|
94
|
+
name: minitest
|
|
95
|
+
requirement: !ruby/object:Gem::Requirement
|
|
96
|
+
requirements:
|
|
97
|
+
- - "~>"
|
|
98
|
+
- !ruby/object:Gem::Version
|
|
99
|
+
version: '5.11'
|
|
100
|
+
- - ">="
|
|
101
|
+
- !ruby/object:Gem::Version
|
|
102
|
+
version: 5.11.3
|
|
103
|
+
type: :development
|
|
104
|
+
prerelease: false
|
|
105
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
106
|
+
requirements:
|
|
107
|
+
- - "~>"
|
|
108
|
+
- !ruby/object:Gem::Version
|
|
109
|
+
version: '5.11'
|
|
110
|
+
- - ">="
|
|
111
|
+
- !ruby/object:Gem::Version
|
|
112
|
+
version: 5.11.3
|
|
113
|
+
- !ruby/object:Gem::Dependency
|
|
114
|
+
name: minitest-unordered
|
|
115
|
+
requirement: !ruby/object:Gem::Requirement
|
|
116
|
+
requirements:
|
|
117
|
+
- - "~>"
|
|
118
|
+
- !ruby/object:Gem::Version
|
|
119
|
+
version: '1.0'
|
|
120
|
+
- - ">="
|
|
121
|
+
- !ruby/object:Gem::Version
|
|
122
|
+
version: 1.0.2
|
|
123
|
+
type: :development
|
|
124
|
+
prerelease: false
|
|
125
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
126
|
+
requirements:
|
|
127
|
+
- - "~>"
|
|
128
|
+
- !ruby/object:Gem::Version
|
|
129
|
+
version: '1.0'
|
|
130
|
+
- - ">="
|
|
131
|
+
- !ruby/object:Gem::Version
|
|
132
|
+
version: 1.0.2
|
|
133
|
+
- !ruby/object:Gem::Dependency
|
|
134
|
+
name: minitest-proveit
|
|
135
|
+
requirement: !ruby/object:Gem::Requirement
|
|
136
|
+
requirements:
|
|
137
|
+
- - "~>"
|
|
138
|
+
- !ruby/object:Gem::Version
|
|
139
|
+
version: '1.0'
|
|
140
|
+
- - ">="
|
|
141
|
+
- !ruby/object:Gem::Version
|
|
142
|
+
version: 1.0.0
|
|
143
|
+
type: :development
|
|
144
|
+
prerelease: false
|
|
145
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
146
|
+
requirements:
|
|
147
|
+
- - "~>"
|
|
148
|
+
- !ruby/object:Gem::Version
|
|
149
|
+
version: '1.0'
|
|
150
|
+
- - ">="
|
|
151
|
+
- !ruby/object:Gem::Version
|
|
152
|
+
version: 1.0.0
|
|
153
|
+
- !ruby/object:Gem::Dependency
|
|
154
|
+
name: minitest-autotest
|
|
155
|
+
requirement: !ruby/object:Gem::Requirement
|
|
156
|
+
requirements:
|
|
157
|
+
- - "~>"
|
|
158
|
+
- !ruby/object:Gem::Version
|
|
159
|
+
version: '1.0'
|
|
160
|
+
- - ">="
|
|
161
|
+
- !ruby/object:Gem::Version
|
|
162
|
+
version: 1.0.3
|
|
163
|
+
type: :development
|
|
164
|
+
prerelease: false
|
|
165
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
166
|
+
requirements:
|
|
167
|
+
- - "~>"
|
|
168
|
+
- !ruby/object:Gem::Version
|
|
169
|
+
version: '1.0'
|
|
170
|
+
- - ">="
|
|
171
|
+
- !ruby/object:Gem::Version
|
|
172
|
+
version: 1.0.3
|
|
173
|
+
description: |
|
|
174
|
+
Lorca is a passphrase generator based on diceware made available by the EFF.
|
|
175
|
+
Passwords, and pins are handle by the system's pseudo-random generator.
|
|
176
|
+
email:
|
|
177
|
+
- rem@disroot.org
|
|
178
|
+
executables:
|
|
179
|
+
- lorca
|
|
180
|
+
extensions: []
|
|
181
|
+
extra_rdoc_files:
|
|
182
|
+
- ChangeLog.md
|
|
183
|
+
- License.md
|
|
184
|
+
- Manifest.md
|
|
185
|
+
- ReadMe.md
|
|
186
|
+
files:
|
|
187
|
+
- ChangeLog.md
|
|
188
|
+
- License.md
|
|
189
|
+
- Manifest.md
|
|
190
|
+
- ReadMe.md
|
|
191
|
+
- _expand_lib_path.rb
|
|
192
|
+
- bin/lorca
|
|
193
|
+
- bin/lorca-alpine
|
|
194
|
+
- lib/lorca.rb
|
|
195
|
+
- lib/lorca/doc.rb
|
|
196
|
+
- lib/lorca/expansions/cli.rb
|
|
197
|
+
- lib/lorca/expansions/phrases.rb
|
|
198
|
+
- lib/lorca/expansions/phrases/eff_large_wordlist.dir
|
|
199
|
+
- lib/lorca/expansions/phrases/eff_large_wordlist.pag
|
|
200
|
+
- lib/lorca/manifest.rb
|
|
201
|
+
- lib/lorca/version.rb
|
|
202
|
+
- test/_config/minitest.rb
|
|
203
|
+
- test/bin/test_lorca.rb
|
|
204
|
+
- test/lib/lorca/expansions/test_cli.rb
|
|
205
|
+
- test/lib/lorca/expansions/test_phrases.rb
|
|
206
|
+
- test/lib/lorca/test_doc.rb
|
|
207
|
+
- test/lib/lorca/test_manifest.rb
|
|
208
|
+
- test/lib/lorca/test_version.rb
|
|
209
|
+
- test/lib/test_lorca.rb
|
|
210
|
+
homepage: https://notabug.org/rem/lorca
|
|
211
|
+
licenses:
|
|
212
|
+
- ISC
|
|
213
|
+
metadata: {}
|
|
214
|
+
post_install_message:
|
|
215
|
+
rdoc_options:
|
|
216
|
+
- "--line-numbers"
|
|
217
|
+
- "--title"
|
|
218
|
+
- 'Lorca: Passphrase, and password generator'
|
|
219
|
+
- "--main"
|
|
220
|
+
- ReadMe.md
|
|
221
|
+
require_paths:
|
|
222
|
+
- lib
|
|
223
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
224
|
+
requirements:
|
|
225
|
+
- - ">="
|
|
226
|
+
- !ruby/object:Gem::Version
|
|
227
|
+
version: '2.4'
|
|
228
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
229
|
+
requirements:
|
|
230
|
+
- - ">="
|
|
231
|
+
- !ruby/object:Gem::Version
|
|
232
|
+
version: '0'
|
|
233
|
+
requirements: []
|
|
234
|
+
rubyforge_project:
|
|
235
|
+
rubygems_version: 2.7.6
|
|
236
|
+
signing_key:
|
|
237
|
+
specification_version: 4
|
|
238
|
+
summary: Passphrase, and password generator
|
|
239
|
+
test_files:
|
|
240
|
+
- test/bin/test_lorca.rb
|
|
241
|
+
- test/lib/lorca/expansions/test_cli.rb
|
|
242
|
+
- test/lib/lorca/expansions/test_phrases.rb
|
|
243
|
+
- test/lib/lorca/test_doc.rb
|
|
244
|
+
- test/lib/lorca/test_manifest.rb
|
|
245
|
+
- test/lib/lorca/test_version.rb
|
|
246
|
+
- test/lib/test_lorca.rb
|