├── .gitignore
├── .travis.yml
├── Exception
├── CharactersNotFoundException.php
├── FileNotFoundException.php
├── ImpossibleMinMaxLimitsException.php
├── ImpossiblePasswordLengthException.php
├── InvalidOptionException.php
├── InvalidOptionTypeException.php
├── NotEnoughWordsException.php
└── WordsNotFoundException.php
├── Generator
├── AbstractPasswordGenerator.php
├── ComputerPasswordGenerator.php
├── DummyPasswordGenerator.php
├── HumanPasswordGenerator.php
├── HybridPasswordGenerator.php
├── PasswordGeneratorInterface.php
├── PronounceablePasswordGenerator.php
└── RequirementPasswordGenerator.php
├── LICENSE
├── Makefile
├── Model
├── CharacterSet.php
└── Option
│ ├── BooleanOption.php
│ ├── IntegerOption.php
│ ├── Option.php
│ ├── OptionInterface.php
│ └── StringOption.php
├── README.md
├── RandomGenerator
├── NoRandomGenerator.php
├── Php5RandomGenerator.php
├── Php7RandomGenerator.php
└── RandomGeneratorInterface.php
├── Tests
├── Generator
│ ├── AbstractPasswordGeneratorClass.php
│ ├── AbstractPasswordGeneratorTest.php
│ ├── ComputerPasswordGeneratorTest.php
│ ├── Data
│ │ └── WordList
│ │ │ ├── empty.txt
│ │ │ └── simple.txt
│ ├── DummyPasswordGeneratorTest.php
│ ├── HumanPasswordGeneratorClass.php
│ ├── HumanPasswordGeneratorTest.php
│ ├── HybridPasswordGeneratorTest.php
│ ├── PronounceablePasswordGeneratorTest.php
│ └── RequirementPasswordGeneratorTest.php
├── Model
│ ├── CharacterSetTest.php
│ └── Option
│ │ ├── BooleanOptionTest.php
│ │ ├── IntegerOptionTest.php
│ │ ├── OptionClass.php
│ │ ├── OptionTest.php
│ │ └── StringOptionTest.php
├── RandomGenerator
│ ├── NoRandomGeneratorTest.php
│ ├── Php5RandomGeneratorTest.php
│ └── Php7RandomGeneratorTest.php
├── ReadMeTest.php
└── bootstrap.php
├── composer.json
├── phpunit.xml.dist
└── travis.phpunit.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | vendor/
2 | composer.lock
3 | /.php_cs.cache
4 | .phpunit
5 | .phpunit.result.cache
6 | /phpunit.xml
7 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 |
3 | php:
4 | - 7.3
5 | - 7.4
6 | - 8.0
7 | - nightly
8 |
9 | env:
10 | global:
11 | - PATH="$HOME/.composer/vendor/bin:$PATH"
12 |
13 | matrix:
14 | fast_finish: true
15 | include:
16 | - php: 8.0
17 | env: CS_FIXER=run
18 | - php: 7.3
19 | env: CS_FIXER=run
20 | - php: 7.3
21 | env: COMPOSER_FLAGS="--prefer-lowest"
22 | allow_failures:
23 | - php: nightly
24 |
25 | sudo: false
26 |
27 | cache:
28 | directories:
29 | - $HOME/.composer/cache
30 |
31 | before_script:
32 | - composer selfupdate
33 | - composer config -g github-oauth.github.com $GITHUB_OAUTH_TOKEN
34 | - composer global require phpunit/phpunit fabpot/php-cs-fixer --no-update
35 | - composer global update --prefer-dist --no-interaction
36 | - composer update --prefer-dist --no-interaction $COMPOSER_FLAGS
37 |
38 | script:
39 | - make test
40 |
--------------------------------------------------------------------------------
/Exception/CharactersNotFoundException.php:
--------------------------------------------------------------------------------
1 | generatePassword();
40 | }
41 |
42 | return $passwords;
43 | }
44 |
45 | /**
46 | * Set password generator option.
47 | *
48 | * @param string $option
49 | * @param array $optionSettings
50 | *
51 | * @return $this
52 | * @throws InvalidOptionTypeException
53 | */
54 | public function setOption($option, $optionSettings)
55 | {
56 | $type = isset($optionSettings['type']) ? $optionSettings['type'] : '';
57 |
58 | $this->options[$option] = Option::createFromType($type, $optionSettings);
59 |
60 | if ($this->options[$option] === null) {
61 | throw new InvalidOptionTypeException('Invalid Option Type');
62 | }
63 |
64 | return $this;
65 | }
66 |
67 | /**
68 | * Remove Option.
69 | *
70 | * @param string $option
71 | *
72 | * @return $this
73 | */
74 | public function removeOption($option)
75 | {
76 | unset($this->options[$option]);
77 |
78 | return $this;
79 | }
80 |
81 | /**
82 | * Get option.
83 | *
84 | * @param $option
85 | *
86 | * @return mixed
87 | */
88 | public function getOption($option)
89 | {
90 | if (!isset($this->options[$option])) {
91 | return;
92 | }
93 |
94 | return $this->options[$option];
95 | }
96 |
97 | /**
98 | * Set password generator option value.
99 | *
100 | * @param string $option
101 | * @param $value
102 | *
103 | * @return $this
104 | */
105 | public function setOptionValue($option, $value)
106 | {
107 | if (!isset($this->options[$option])) {
108 | throw new InvalidOptionException('Invalid Option');
109 | }
110 |
111 | $this->options[$option]->setValue($value);
112 |
113 | return $this;
114 | }
115 |
116 | /**
117 | * Get option value.
118 | *
119 | * @param $option
120 | *
121 | * @return mixed
122 | */
123 | public function getOptionValue($option)
124 | {
125 | if (!isset($this->options[$option])) {
126 | throw new InvalidOptionException('Invalid Option');
127 | }
128 |
129 | return $this->options[$option]->getValue();
130 | }
131 |
132 | /**
133 | * @param string $parameter
134 | * @param mixed $value
135 | *
136 | * @return $this
137 | */
138 | public function setParameter($parameter, $value)
139 | {
140 | $this->parameters[$parameter] = $value;
141 |
142 | return $this;
143 | }
144 |
145 | /**
146 | * @param string $parameter
147 | * @param mixed $default
148 | *
149 | * @return null|mixed
150 | */
151 | public function getParameter($parameter, $default = null)
152 | {
153 | if (!isset($this->parameters[$parameter])) {
154 | return $default;
155 | }
156 |
157 | return $this->parameters[$parameter];
158 | }
159 |
160 | /**
161 | * Possible options.
162 | *
163 | * @return array
164 | */
165 | public function getOptions()
166 | {
167 | return $this->options;
168 | }
169 |
170 | /**
171 | * Set source of randomness.
172 | *
173 | * @param RandomGeneratorInterface $randomGenerator
174 | *
175 | * @return $this
176 | */
177 | public function setRandomGenerator(RandomGeneratorInterface $randomGenerator)
178 | {
179 | $this->randomGenerator = $randomGenerator;
180 |
181 | return $this;
182 | }
183 |
184 | /**
185 | * Generate a random value
186 | * Fallback to mt_rand if none provided.
187 | *
188 | * @param int $min
189 | * @param int $max
190 | *
191 | * @return int
192 | */
193 | public function randomInteger($min, $max)
194 | {
195 | if (!$this->randomGenerator) {
196 | $this->randomGenerator = new Php7RandomGenerator();
197 | }
198 |
199 | return $this->randomGenerator->randomInteger($min, $max);
200 | }
201 | }
202 |
--------------------------------------------------------------------------------
/Generator/ComputerPasswordGenerator.php:
--------------------------------------------------------------------------------
1 | setOption(self::OPTION_UPPER_CASE, array('type' => Option::TYPE_BOOLEAN, 'default' => true))
30 | ->setOption(self::OPTION_LOWER_CASE, array('type' => Option::TYPE_BOOLEAN, 'default' => true))
31 | ->setOption(self::OPTION_NUMBERS, array('type' => Option::TYPE_BOOLEAN, 'default' => true))
32 | ->setOption(self::OPTION_SYMBOLS, array('type' => Option::TYPE_BOOLEAN, 'default' => false))
33 | ->setOption(self::OPTION_AVOID_SIMILAR, array('type' => Option::TYPE_BOOLEAN, 'default' => true))
34 | ->setOption(self::OPTION_LENGTH, array('type' => Option::TYPE_INTEGER, 'default' => 10))
35 | ->setParameter(self::PARAMETER_UPPER_CASE, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')
36 | ->setParameter(self::PARAMETER_LOWER_CASE, 'abcdefghijklmnopqrstuvwxyz')
37 | ->setParameter(self::PARAMETER_NUMBERS, '0123456789')
38 | ->setParameter(self::PARAMETER_SYMBOLS, '!@$%^&*()<>,.?/[]{}-=_+')
39 | ->setParameter(self::PARAMETER_SIMILAR, 'iIl1Oo0')
40 | ;
41 | }
42 |
43 | /**
44 | * Generate character list for us in generating passwords.
45 | *
46 | * @return CharacterSet Character list
47 | *
48 | * @throws CharactersNotFoundException
49 | */
50 | public function getCharacterList()
51 | {
52 | $characters = '';
53 |
54 | if ($this->getOptionValue(self::OPTION_UPPER_CASE)) {
55 | $characters .= $this->getParameter(self::PARAMETER_UPPER_CASE, '');
56 | }
57 |
58 | if ($this->getOptionValue(self::OPTION_LOWER_CASE)) {
59 | $characters .= $this->getParameter(self::PARAMETER_LOWER_CASE, '');
60 | }
61 |
62 | if ($this->getOptionValue(self::OPTION_NUMBERS)) {
63 | $characters .= $this->getParameter(self::PARAMETER_NUMBERS, '');
64 | }
65 |
66 | if ($this->getOptionValue(self::OPTION_SYMBOLS)) {
67 | $characters .= $this->getParameter(self::PARAMETER_SYMBOLS, '');
68 | }
69 |
70 | if ($this->getOptionValue(self::OPTION_AVOID_SIMILAR)) {
71 | $removeCharacters = \mb_str_split($this->getParameter(self::PARAMETER_SIMILAR, ''));
72 | $characters = \str_replace($removeCharacters, '', $characters);
73 | }
74 |
75 | if (!$characters) {
76 | throw new CharactersNotFoundException('No character sets selected.');
77 | }
78 |
79 | return new CharacterSet($characters);
80 | }
81 |
82 | /**
83 | * Generate one password based on options.
84 | *
85 | * @return string password
86 | */
87 | public function generatePassword()
88 | {
89 | $characterList = $this->getCharacterList()->getCharacters();
90 | $characters = \mb_strlen($characterList);
91 | $password = '';
92 |
93 | $length = $this->getLength();
94 |
95 | for ($i = 0; $i < $length; ++$i) {
96 | $randomIndex = $this->randomInteger(0, $characters - 1);
97 | $password .= \mb_substr($characterList, $randomIndex, 1);
98 | }
99 |
100 | return $password;
101 | }
102 |
103 | /**
104 | * Password length.
105 | */
106 | public function getLength()
107 | {
108 | return $this->getOptionValue(self::OPTION_LENGTH);
109 | }
110 |
111 | /**
112 | * Set length of desired password(s).
113 | *
114 | * @param int $characterCount
115 | *
116 | * @return $this
117 | *
118 | * @throws \InvalidArgumentException
119 | */
120 | public function setLength($characterCount)
121 | {
122 | if (!is_int($characterCount) || $characterCount < 1) {
123 | throw new \InvalidArgumentException('Expected positive integer');
124 | }
125 |
126 | $this->setOptionValue(self::OPTION_LENGTH, $characterCount);
127 |
128 | return $this;
129 | }
130 |
131 | /**
132 | * Are Uppercase characters enabled?
133 | *
134 | * @return bool
135 | */
136 | public function getUppercase()
137 | {
138 | return $this->getOptionValue(self::OPTION_UPPER_CASE);
139 | }
140 |
141 | /**
142 | * Enable uppercase characters.
143 | *
144 | * @param bool $enable
145 | *
146 | * @return $this
147 | *
148 | * @throws \InvalidArgumentException
149 | */
150 | public function setUppercase($enable = true)
151 | {
152 | if (!is_bool($enable)) {
153 | throw new \InvalidArgumentException('Expected boolean');
154 | }
155 |
156 | $this->setOptionValue(self::OPTION_UPPER_CASE, $enable);
157 |
158 | return $this;
159 | }
160 |
161 | /**
162 | * Are Lowercase characters enabled?
163 | *
164 | * @return string
165 | */
166 | public function getLowercase()
167 | {
168 | return $this->getOptionValue(self::OPTION_LOWER_CASE);
169 | }
170 |
171 | /**
172 | * Enable lowercase characters.
173 | *
174 | * @param bool $enable
175 | *
176 | * @return $this
177 | *
178 | * @throws \InvalidArgumentException
179 | */
180 | public function setLowercase($enable = true)
181 | {
182 | if (!is_bool($enable)) {
183 | throw new \InvalidArgumentException('Expected boolean');
184 | }
185 |
186 | $this->setOptionValue(self::OPTION_LOWER_CASE, $enable);
187 |
188 | return $this;
189 | }
190 |
191 | /**
192 | * Are Numbers enabled?
193 | *
194 | * @return string
195 | */
196 | public function getNumbers()
197 | {
198 | return $this->getOptionValue(self::OPTION_NUMBERS);
199 | }
200 |
201 | /**
202 | * Enable numbers.
203 | *
204 | * @param bool $enable
205 | *
206 | * @return $this
207 | *
208 | * @throws \InvalidArgumentException
209 | */
210 | public function setNumbers($enable = true)
211 | {
212 | if (!is_bool($enable)) {
213 | throw new \InvalidArgumentException('Expected boolean');
214 | }
215 |
216 | $this->setOptionValue(self::OPTION_NUMBERS, $enable);
217 |
218 | return $this;
219 | }
220 |
221 | /**
222 | * Are Symbols enabled?
223 | *
224 | * @return string
225 | */
226 | public function getSymbols()
227 | {
228 | return $this->getOptionValue(self::OPTION_SYMBOLS);
229 | }
230 |
231 | /**
232 | * Enable symbol characters.
233 | *
234 | * @param bool $enable
235 | *
236 | * @return $this
237 | *
238 | * @throws \InvalidArgumentException
239 | */
240 | public function setSymbols($enable = true)
241 | {
242 | if (!is_bool($enable)) {
243 | throw new \InvalidArgumentException('Expected boolean');
244 | }
245 |
246 | $this->setOptionValue(self::OPTION_SYMBOLS, $enable);
247 |
248 | return $this;
249 | }
250 |
251 | /**
252 | * Avoid similar characters enabled?
253 | *
254 | * @return string
255 | */
256 | public function getAvoidSimilar()
257 | {
258 | return $this->getOptionValue(self::OPTION_AVOID_SIMILAR);
259 | }
260 |
261 | /**
262 | * Enable characters to be removed when avoiding similar characters.
263 | *
264 | * @param bool $enable
265 | *
266 | * @return $this
267 | *
268 | * @throws \InvalidArgumentException
269 | */
270 | public function setAvoidSimilar($enable = true)
271 | {
272 | if (!is_bool($enable)) {
273 | throw new \InvalidArgumentException('Expected boolean');
274 | }
275 |
276 | $this->setOptionValue(self::OPTION_AVOID_SIMILAR, $enable);
277 |
278 | return $this;
279 | }
280 | }
281 |
--------------------------------------------------------------------------------
/Generator/DummyPasswordGenerator.php:
--------------------------------------------------------------------------------
1 | setOption(self::OPTION_LENGTH, array('type' => Option::TYPE_INTEGER, 'default' => 10))
17 | ;
18 | }
19 |
20 | public function generatePassword()
21 | {
22 | $length = $this->getOptionValue(self::OPTION_LENGTH);
23 |
24 | if ($length < 8) {
25 | return \mb_substr('password', 0, $length);
26 | }
27 |
28 | return str_pad('password', $length, '?');
29 | }
30 |
31 | /**
32 | * Password length.
33 | *
34 | * @return int
35 | */
36 | public function getLength()
37 | {
38 | return $this->getOptionValue(self::OPTION_LENGTH);
39 | }
40 |
41 | /**
42 | * Set length of desired password(s).
43 | *
44 | * @param int $characterCount
45 | *
46 | * @return $this
47 | *
48 | * @throws \InvalidArgumentException
49 | */
50 | public function setLength($characterCount)
51 | {
52 | if (!is_int($characterCount) || $characterCount < 1) {
53 | throw new \InvalidArgumentException('Expected positive integer');
54 | }
55 |
56 | $this->setOptionValue(self::OPTION_LENGTH, $characterCount);
57 |
58 | return $this;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/Generator/HumanPasswordGenerator.php:
--------------------------------------------------------------------------------
1 | setOption(self::OPTION_LENGTH, array('type' => Option::TYPE_INTEGER, 'default' => null))
29 | ->setOption(self::OPTION_WORDS, array('type' => Option::TYPE_INTEGER, 'default' => 4))
30 | ->setOption(self::OPTION_MIN_WORD_LENGTH, array('type' => Option::TYPE_INTEGER, 'default' => 3))
31 | ->setOption(self::OPTION_MAX_WORD_LENGTH, array('type' => Option::TYPE_INTEGER, 'default' => 20))
32 | ->setParameter(self::PARAMETER_WORD_SEPARATOR, '')
33 | ;
34 | }
35 |
36 | /**
37 | * Generate word list for us in generating passwords.
38 | *
39 | * @return string[] Words
40 | *
41 | * @throws WordsNotFoundException
42 | */
43 | public function generateWordList()
44 | {
45 | if ($this->getParameter(self::PARAMETER_WORD_CACHE) !== null) {
46 | $this->findWordListLength();
47 |
48 | return $this->getParameter(self::PARAMETER_WORD_CACHE);
49 | }
50 |
51 | $words = explode("\n", \file_get_contents($this->getWordList()));
52 |
53 | $minWordLength = $this->getOptionValue(self::OPTION_MIN_WORD_LENGTH);
54 | $maxWordLength = $this->getOptionValue(self::OPTION_MAX_WORD_LENGTH);
55 |
56 | foreach ($words as $i => $word) {
57 | $words[$i] = trim($word);
58 | $wordLength = \mb_strlen($word);
59 |
60 | if ($wordLength > $maxWordLength || $wordLength < $minWordLength) {
61 | unset($words[$i]);
62 | }
63 | }
64 |
65 | $words = \array_values($words);
66 |
67 | if (!$words) {
68 | throw new WordsNotFoundException('No words selected.');
69 | }
70 |
71 | $this->setParameter(self::PARAMETER_WORD_CACHE, $words);
72 | $this->findWordListLength();
73 |
74 | return $words;
75 | }
76 |
77 | private function findWordListLength()
78 | {
79 | $words = $this->getParameter(self::PARAMETER_WORD_CACHE);
80 |
81 | $this->minWordLength = INF;
82 | $this->maxWordLength = 0;
83 |
84 | foreach ($words as $word) {
85 | $wordLength = \mb_strlen($word);
86 |
87 | $this->minWordLength = min($wordLength, $this->minWordLength);
88 | $this->maxWordLength = max($wordLength, $this->maxWordLength);
89 | }
90 | }
91 |
92 | private function generateWordListSubset($min, $max)
93 | {
94 | $wordList = $this->generateWordList();
95 | $newWordList = array();
96 |
97 | foreach ($wordList as $word) {
98 | $wordLength = mb_strlen($word);
99 |
100 | if ($wordLength < $min || $wordLength > $max) {
101 | continue;
102 | }
103 |
104 | $newWordList[] = $word;
105 | }
106 |
107 | return $newWordList;
108 | }
109 |
110 | /**
111 | * Generate one password based on options.
112 | *
113 | * @return string password
114 | *
115 | * @throws WordsNotFoundException
116 | * @throws ImpossiblePasswordLengthException
117 | */
118 | public function generatePassword()
119 | {
120 | $wordList = $this->generateWordList();
121 |
122 | $words = \count($wordList);
123 |
124 | if (!$words) {
125 | throw new WordsNotFoundException('No words selected.');
126 | }
127 |
128 | $password = '';
129 | $wordCount = $this->getWordCount();
130 |
131 | if (
132 | $this->getLength() > 0 &&
133 | (
134 | $this->getMinPasswordLength() > $this->getLength()
135 | ||
136 | $this->getMaxPasswordLength() < $this->getLength()
137 | )
138 | ) {
139 | throw new ImpossiblePasswordLengthException();
140 | }
141 |
142 | if (!$this->getLength()) {
143 | for ($i = 0; $i < $wordCount; $i++) {
144 | if ($i) {
145 | $password .= $this->getWordSeparator();
146 | }
147 |
148 | $password .= $this->randomWord();
149 | }
150 |
151 | return $password;
152 | }
153 |
154 | while(--$wordCount) {
155 | $thisMin = $this->getLength() - mb_strlen($password) - ($wordCount * $this->getMaxWordLength()) - (mb_strlen($this->getWordSeparator()) * $wordCount);
156 | $thisMax = $this->getLength() - mb_strlen($password) - ($wordCount * $this->getMinWordLength()) - (mb_strlen($this->getWordSeparator()) * $wordCount);
157 |
158 | if ($thisMin < 1) {
159 | $thisMin = $this->getMinWordLength();
160 | }
161 |
162 | if ($thisMax > $this->getMaxWordLength()) {
163 | $thisMax = $this->getMaxWordLength();
164 | }
165 |
166 | $length = $this->randomInteger($thisMin, $thisMax);
167 |
168 | $password .= $this->randomWord($length, $length);
169 |
170 | if ($wordCount) {
171 | $password .= $this->getWordSeparator();
172 | }
173 | }
174 |
175 | $desiredLength = $this->getLength() - mb_strlen($password);
176 | $password .= $this->randomWord($desiredLength, $desiredLength);
177 |
178 | return $password;
179 | }
180 |
181 | /**
182 | * @param null|int $minLength
183 | * @param null|int $maxLength
184 | *
185 | * @return string
186 | *
187 | * @throws NotEnoughWordsException
188 | */
189 | public function randomWord($minLength = null, $maxLength = null)
190 | {
191 | if (is_null($minLength)) {
192 | $minLength = $this->getMinWordLength();
193 | }
194 |
195 | if (is_null($maxLength)) {
196 | $maxLength = $this->getMaxWordLength();
197 | }
198 |
199 | $wordList = $this->generateWordListSubset($minLength, $maxLength);
200 | $words = \count($wordList);
201 |
202 | if (!$words) {
203 | throw new NotEnoughWordsException(sprintf('No words with a length between %d and %d', $minLength, $maxLength));
204 | }
205 |
206 | return $wordList[$this->randomInteger(0, $words - 1)];
207 | }
208 |
209 | /**
210 | * Get number of words in desired password.
211 | *
212 | * @return int
213 | */
214 | public function getWordCount()
215 | {
216 | return $this->getOptionValue(self::OPTION_WORDS);
217 | }
218 |
219 | /**
220 | * Set number of words in desired password(s).
221 | *
222 | * @param int $characterCount
223 | *
224 | * @return $this
225 | *
226 | * @throws \InvalidArgumentException
227 | */
228 | public function setWordCount($characterCount)
229 | {
230 | if (!is_int($characterCount) || $characterCount < 1) {
231 | throw new \InvalidArgumentException('Expected positive integer');
232 | }
233 |
234 | $this->setOptionValue(self::OPTION_WORDS, $characterCount);
235 |
236 | return $this;
237 | }
238 |
239 | /**
240 | * get max word length.
241 | *
242 | * @return int
243 | */
244 | public function getMaxWordLength()
245 | {
246 | if (is_null($this->maxWordLength)) {
247 | return $this->getOptionValue(self::OPTION_MAX_WORD_LENGTH);
248 | }
249 |
250 | return min(
251 | $this->maxWordLength,
252 | $this->getOptionValue(self::OPTION_MAX_WORD_LENGTH)
253 | );
254 | }
255 |
256 | /**
257 | * set max word length.
258 | *
259 | * @param int $length
260 | *
261 | * @return $this
262 | *
263 | * @throws \InvalidArgumentException
264 | */
265 | public function setMaxWordLength($length)
266 | {
267 | if (!is_int($length) || $length < 1) {
268 | throw new \InvalidArgumentException('Expected positive integer');
269 | }
270 |
271 | $this->setOptionValue(self::OPTION_MAX_WORD_LENGTH, $length);
272 | $this->setParameter(self::PARAMETER_WORD_CACHE, null);
273 | $this->minWordLength = null;
274 | $this->maxWordLength = null;
275 |
276 | return $this;
277 | }
278 |
279 | /**
280 | * get min word length.
281 | *
282 | * @return int
283 | */
284 | public function getMinWordLength()
285 | {
286 | return max(
287 | $this->minWordLength,
288 | $this->getOptionValue(self::OPTION_MIN_WORD_LENGTH)
289 | );
290 | }
291 |
292 | /**
293 | * set min word length.
294 | *
295 | * @param int $length
296 | *
297 | * @return $this
298 | *
299 | * @throws \InvalidArgumentException
300 | */
301 | public function setMinWordLength($length)
302 | {
303 | if (!is_int($length) || $length < 1) {
304 | throw new \InvalidArgumentException('Expected positive integer');
305 | }
306 |
307 | $this->setOptionValue(self::OPTION_MIN_WORD_LENGTH, $length);
308 | $this->setParameter(self::PARAMETER_WORD_CACHE, null);
309 | $this->minWordLength = null;
310 | $this->maxWordLength = null;
311 |
312 | return $this;
313 | }
314 |
315 | /**
316 | * Set word list.
317 | *
318 | * @param string $filename
319 | *
320 | * @return $this
321 | *
322 | * @throws \InvalidArgumentException
323 | * @throws FileNotFoundException
324 | */
325 | public function setWordList($filename)
326 | {
327 | if (!is_string($filename)) {
328 | throw new \InvalidArgumentException('Expected string');
329 | } elseif (!file_exists($filename)) {
330 | throw new FileNotFoundException('File not found');
331 | }
332 |
333 | $this->setParameter(self::PARAMETER_DICTIONARY_FILE, $filename);
334 | $this->setParameter(self::PARAMETER_WORD_CACHE, null);
335 |
336 | return $this;
337 | }
338 |
339 | /**
340 | * Get word list filename.
341 | *
342 | * @throws FileNotFoundException
343 | *
344 | * @return string
345 | */
346 | public function getWordList()
347 | {
348 | $filename = $this->getParameter(self::PARAMETER_DICTIONARY_FILE);
349 |
350 | if ($filename === null || !file_exists($filename)) {
351 | throw new FileNotFoundException($filename ?? 'No file provided');
352 | }
353 |
354 | return $filename;
355 | }
356 |
357 | /**
358 | * Get word separator.
359 | *
360 | * @return string
361 | */
362 | public function getWordSeparator()
363 | {
364 | return $this->getParameter(self::PARAMETER_WORD_SEPARATOR);
365 | }
366 |
367 | /**
368 | * Set word separator.
369 | *
370 | * @param string $separator
371 | *
372 | * @return $this
373 | *
374 | * @throws \InvalidArgumentException
375 | */
376 | public function setWordSeparator($separator)
377 | {
378 | if (!is_string($separator)) {
379 | throw new \InvalidArgumentException('Expected string');
380 | }
381 |
382 | $this->setParameter(self::PARAMETER_WORD_SEPARATOR, $separator);
383 |
384 | return $this;
385 | }
386 |
387 | /**
388 | * Password length
389 | *
390 | * @return integer
391 | */
392 | public function getLength()
393 | {
394 | return $this->getOptionValue(self::OPTION_LENGTH);
395 | }
396 |
397 | /**
398 | * Set length of desired password(s)
399 | *
400 | * @param integer $characterCount
401 | *
402 | * @return $this
403 | *
404 | * @throws \InvalidArgumentException
405 | */
406 | public function setLength($characterCount)
407 | {
408 | if (!is_int($characterCount) || $characterCount < 1) {
409 | throw new \InvalidArgumentException('Expected positive integer');
410 | }
411 |
412 | $this->setOptionValue(self::OPTION_LENGTH, $characterCount);
413 |
414 | return $this;
415 | }
416 |
417 | /**
418 | * Calculate how long the password would be using minimum word length
419 | *
420 | * @return int
421 | */
422 | public function getMinPasswordLength()
423 | {
424 | $wordCount = $this->getWordCount();
425 |
426 | return ($this->getMinWordLength() * $wordCount) + (mb_strlen($this->getWordSeparator()) * ($wordCount - 1));
427 | }
428 |
429 | /**
430 | * Calculate how long the password would be using maximum word length
431 | *
432 | * @return int
433 | */
434 | public function getMaxPasswordLength()
435 | {
436 | $wordCount = $this->getWordCount();
437 |
438 | return ($this->getMaxWordLength() * $wordCount) + (mb_strlen($this->getWordSeparator()) * ($wordCount - 1));
439 | }
440 | }
441 |
--------------------------------------------------------------------------------
/Generator/HybridPasswordGenerator.php:
--------------------------------------------------------------------------------
1 | removeOption(self::OPTION_LENGTH)
21 | ->setOption(self::OPTION_SEGMENT_COUNT, array('type' => Option::TYPE_INTEGER, 'default' => 4))
22 | ->setOption(self::OPTION_SEGMENT_LENGTH, array('type' => Option::TYPE_INTEGER, 'default' => 3))
23 | ->setParameter(self::PARAMETER_SEPARATOR, '-')
24 | ;
25 | }
26 |
27 | /**
28 | * Generate character list for us in generating passwords
29 | * and remove segment separator from character list pool.
30 | *
31 | * @return CharacterSet Character list
32 | *
33 | * @throws \Exception
34 | */
35 | public function getCharacterList()
36 | {
37 | $characterList = parent::getCharacterList();
38 | $characterList = \str_replace($this->getSegmentSeparator(), '', $characterList);
39 |
40 | return new CharacterSet($characterList);
41 | }
42 |
43 | /**
44 | * Generate one password based on options.
45 | *
46 | * @return string password
47 | */
48 | public function generatePassword()
49 | {
50 | $characterList = $this->getCharacterList()->getCharacters();
51 | $characters = \mb_strlen($characterList);
52 | $password = '';
53 |
54 | $segmentCount = $this->getSegmentCount();
55 | $segmentLength = $this->getSegmentLength();
56 |
57 | for ($i = 0; $i < $segmentCount; ++$i) {
58 | if ($password) {
59 | $password .= $this->getSegmentSeparator();
60 | }
61 |
62 | for ($j = 0; $j < $segmentLength; ++$j) {
63 | $password .= $characterList[$this->randomInteger(0, $characters - 1)];
64 | }
65 | }
66 |
67 | return $password;
68 | }
69 |
70 | /**
71 | * Get number of words in desired password.
72 | *
73 | * @return int
74 | */
75 | public function getLength()
76 | {
77 | return $this->getSegmentCount();
78 | }
79 |
80 | /**
81 | * Set length of desired password(s).
82 | *
83 | * @param int $characterCount
84 | *
85 | * @return $this
86 | *
87 | * @throws \InvalidArgumentException
88 | */
89 | public function setLength($characterCount)
90 | {
91 | $this->setSegmentCount($characterCount);
92 |
93 | return $this;
94 | }
95 |
96 | /**
97 | * Get number of segments in desired password.
98 | *
99 | * @return int
100 | */
101 | public function getSegmentCount()
102 | {
103 | return $this->getOptionValue(self::OPTION_SEGMENT_COUNT);
104 | }
105 |
106 | /**
107 | * Set number of segments in desired password(s).
108 | *
109 | * @param int $segmentCount
110 | *
111 | * @return $this
112 | *
113 | * @throws \InvalidArgumentException
114 | */
115 | public function setSegmentCount($segmentCount)
116 | {
117 | if (!is_int($segmentCount) || $segmentCount < 1) {
118 | throw new \InvalidArgumentException('Expected positive integer');
119 | }
120 |
121 | $this->setOptionValue(self::OPTION_SEGMENT_COUNT, $segmentCount);
122 |
123 | return $this;
124 | }
125 |
126 | /**
127 | * Get number of segments in desired password.
128 | *
129 | * @return int
130 | */
131 | public function getSegmentLength()
132 | {
133 | return $this->getOptionValue(self::OPTION_SEGMENT_LENGTH);
134 | }
135 |
136 | /**
137 | * Set length of segment.
138 | *
139 | * @param int $segmentLength
140 | *
141 | * @return $this
142 | *
143 | * @throws \InvalidArgumentException
144 | */
145 | public function setSegmentLength($segmentLength)
146 | {
147 | if (!is_int($segmentLength) || $segmentLength < 1) {
148 | throw new \InvalidArgumentException('Expected positive integer');
149 | }
150 |
151 | $this->setOptionValue(self::OPTION_SEGMENT_LENGTH, $segmentLength);
152 |
153 | return $this;
154 | }
155 |
156 | /**
157 | * Get Segment Separator.
158 | *
159 | * @return string
160 | */
161 | public function getSegmentSeparator()
162 | {
163 | return $this->getParameter(self::PARAMETER_SEPARATOR);
164 | }
165 |
166 | /**
167 | * Set segment separator.
168 | *
169 | * @param string $segmentSeparator
170 | *
171 | * @return \Hackzilla\PasswordGenerator\Generator\HybridPasswordGenerator
172 | *
173 | * @throws \InvalidArgumentException
174 | */
175 | public function setSegmentSeparator($segmentSeparator)
176 | {
177 | if (!is_string($segmentSeparator)) {
178 | throw new \InvalidArgumentException('Expected string');
179 | }
180 |
181 | $this->setParameter(self::PARAMETER_SEPARATOR, $segmentSeparator);
182 |
183 | return $this;
184 | }
185 | }
186 |
--------------------------------------------------------------------------------
/Generator/PasswordGeneratorInterface.php:
--------------------------------------------------------------------------------
1 | setParameter(self::PARAMETER_VOWELS, 'aeiou');
16 | }
17 |
18 | public function generatePassword()
19 | {
20 | $vowels = $this->getParameter(self::PARAMETER_VOWELS, '');
21 |
22 | if (!mb_strlen($vowels)) {
23 | return parent::generatePassword();
24 | }
25 |
26 | $characterList = $this->getCharacterList()->getCharacters();
27 | $charactersCount = mb_strlen($characterList);
28 | $password = '';
29 |
30 | $length = $this->getLength();
31 | $isLastCharVowel = null;
32 |
33 | for ($i = 0; $i < $length; ++$i) {
34 | do {
35 | $char = $characterList[$this->randomInteger(0, $charactersCount - 1)];
36 | $isVowel = false !== stripos($vowels, $char);
37 |
38 | } while (null !== $isLastCharVowel && $isVowel === $isLastCharVowel);
39 |
40 | $password .= $char;
41 | $isLastCharVowel = $isVowel;
42 | }
43 |
44 | return $password;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Generator/RequirementPasswordGenerator.php:
--------------------------------------------------------------------------------
1 | validOptions = array(
29 | self::OPTION_UPPER_CASE,
30 | self::OPTION_LOWER_CASE,
31 | self::OPTION_NUMBERS,
32 | self::OPTION_SYMBOLS,
33 | );
34 | }
35 |
36 | /**
37 | * Generate one password based on options.
38 | *
39 | * @return string password
40 | * @throws ImpossibleMinMaxLimitsException
41 | * @throws \Hackzilla\PasswordGenerator\Exception\CharactersNotFoundException
42 | */
43 | public function generatePassword()
44 | {
45 | if ($this->dirtyCheck) {
46 | if (!$this->validLimits()) {
47 | throw new ImpossibleMinMaxLimitsException();
48 | }
49 |
50 | $this->dirtyCheck = false;
51 | }
52 |
53 | do {
54 | $password = parent::generatePassword();
55 | } while (!$this->validatePassword($password));
56 |
57 | return $password;
58 | }
59 |
60 | /**
61 | * Password minimum count for option.
62 | *
63 | * @param string $option Use class constants
64 | *
65 | * @return int|null
66 | */
67 | public function getMinimumCount($option)
68 | {
69 | return isset($this->minimumCounts[$option]) ? $this->minimumCounts[$option] : null;
70 | }
71 |
72 | /**
73 | * Password maximum count for option.
74 | *
75 | * @param string $option Use class constants
76 | *
77 | * @return int|null
78 | */
79 | public function getMaximumCount($option)
80 | {
81 | return isset($this->maximumCounts[$option]) ? $this->maximumCounts[$option] : null;
82 | }
83 |
84 | /**
85 | * Set minimum count of option for desired password(s).
86 | *
87 | * @param string $option Use class constants
88 | * @param int|null $characterCount
89 | *
90 | * @return $this
91 | *
92 | * @throws InvalidOptionException
93 | */
94 | public function setMinimumCount($option, $characterCount)
95 | {
96 | $this->dirtyCheck = true;
97 |
98 | if (!$this->validOption($option)) {
99 | throw new InvalidOptionException('Invalid Option');
100 | }
101 |
102 | if (is_null($characterCount)) {
103 | unset($this->minimumCounts[$option]);
104 |
105 | return $this;
106 | }
107 |
108 | if (!is_int($characterCount) || $characterCount < 0) {
109 | throw new \InvalidArgumentException('Expected non-negative integer');
110 | }
111 |
112 | $this->minimumCounts[$option] = $characterCount;
113 |
114 | return $this;
115 | }
116 |
117 | /**
118 | * Set maximum count of option for desired password(s).
119 | *
120 | * @param string $option Use class constants
121 | * @param int|null $characterCount
122 | *
123 | * @return $this
124 | *
125 | * @throws InvalidOptionException
126 | */
127 | public function setMaximumCount($option, $characterCount)
128 | {
129 | $this->dirtyCheck = true;
130 |
131 | if (!$this->validOption($option)) {
132 | throw new InvalidOptionException('Invalid Option');
133 | }
134 |
135 | if (is_null($characterCount)) {
136 | unset($this->maximumCounts[$option]);
137 |
138 | return $this;
139 | }
140 |
141 | if (!is_int($characterCount) || $characterCount < 0) {
142 | throw new \InvalidArgumentException('Expected non-negative integer');
143 | }
144 |
145 | $this->maximumCounts[$option] = $characterCount;
146 |
147 | return $this;
148 | }
149 |
150 | public function validLimits()
151 | {
152 | $elements = 0;
153 |
154 | if ($this->getOptionValue(self::OPTION_UPPER_CASE)) {
155 | $elements++;
156 | }
157 |
158 | if ($this->getOptionValue(self::OPTION_LOWER_CASE)) {
159 | $elements++;
160 | }
161 |
162 | if ($this->getOptionValue(self::OPTION_NUMBERS)) {
163 | $elements++;
164 | }
165 |
166 | if ($this->getOptionValue(self::OPTION_SYMBOLS)) {
167 | $elements++;
168 | }
169 |
170 | // check if there is wiggle room in minimums
171 | $total = 0;
172 |
173 | foreach ($this->minimumCounts as $minOption => $minCount) {
174 | $total += $minCount;
175 | }
176 |
177 | if ($total > $this->getLength()) {
178 | return false;
179 | }
180 |
181 | // check if there is wiggle room in maximums
182 | if ($elements <= count($this->maximumCounts)) {
183 | $total = 0;
184 |
185 | foreach ($this->maximumCounts as $maxOption => $maxCount) {
186 | $total += $maxCount;
187 | }
188 |
189 | if ($total < $this->getLength()) {
190 | return false;
191 | }
192 | }
193 |
194 | return true;
195 | }
196 |
197 | /**
198 | * @param string $option
199 | *
200 | * @return bool
201 | */
202 | public function validOption($option)
203 | {
204 | return in_array($option, $this->validOptions, true);
205 | }
206 |
207 | /**
208 | * Generate $count number of passwords.
209 | *
210 | * @param int $count Number of passwords to return
211 | *
212 | * @return array
213 | *
214 | * @throws \InvalidArgumentException
215 | */
216 | public function generatePasswords($count = 1)
217 | {
218 | if (!is_int($count)) {
219 | throw new \InvalidArgumentException('Expected integer');
220 | } elseif ($count < 0) {
221 | throw new \InvalidArgumentException('Expected positive integer');
222 | }
223 |
224 | $passwords = array();
225 |
226 | for ($i = 0; $i < $count; $i++) {
227 | $passwords[] = $this->generatePassword();
228 | }
229 |
230 | return $passwords;
231 | }
232 |
233 | /**
234 | * Check password is valid when comparing to minimum and maximum counts of options.
235 | *
236 | * @param string $password
237 | *
238 | * @return bool
239 | */
240 | public function validatePassword($password)
241 | {
242 | foreach ($this->validOptions as $option) {
243 | $minCount = $this->getMinimumCount($option);
244 | $maxCount = $this->getMaximumCount($option);
245 | $count = mb_strlen(preg_replace('|[^'.preg_quote($this->getParameter($option)).']|u', '', $password));
246 |
247 | if (!is_null($minCount) && $count < $minCount) {
248 | return false;
249 | }
250 |
251 | if (!is_null($maxCount) && $count > $maxCount) {
252 | return false;
253 | }
254 | }
255 |
256 | return true;
257 | }
258 | }
259 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Daniel Platt
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | test:
2 | mkdir -p build/logs
3 | php vendor/bin/phpunit
4 |
--------------------------------------------------------------------------------
/Model/CharacterSet.php:
--------------------------------------------------------------------------------
1 | characters = $characters;
17 | }
18 |
19 | /**
20 | * Get Character set
21 | *
22 | * @return string
23 | */
24 | public function getCharacters(): string
25 | {
26 | return $this->characters;
27 | }
28 |
29 | /**
30 | * @return string
31 | */
32 | public function __toString()
33 | {
34 | return $this->characters;
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/Model/Option/BooleanOption.php:
--------------------------------------------------------------------------------
1 | minRange = isset($settings['min']) ? $settings['min'] : ~PHP_INT_MAX;
20 | $this->maxRange = isset($settings['max']) ? $settings['max'] : PHP_INT_MAX;
21 | }
22 |
23 | /**
24 | * {@inheritdoc}
25 | */
26 | public function setValue($value)
27 | {
28 | if (!is_integer($value)) {
29 | throw new InvalidArgumentException('Integer required');
30 | }
31 |
32 | if ($this->minRange > $value || $this->maxRange < $value) {
33 | throw new InvalidArgumentException('Invalid Value');
34 | }
35 |
36 | parent::setValue($value);
37 | }
38 |
39 | /**
40 | * {@inheritdoc}
41 | */
42 | public function getType()
43 | {
44 | return self::TYPE_INTEGER;
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/Model/Option/Option.php:
--------------------------------------------------------------------------------
1 | value = $settings['default'];
20 | }
21 | }
22 |
23 | /**
24 | * {@inheritdoc}
25 | */
26 | public function getValue()
27 | {
28 | return $this->value;
29 | }
30 |
31 | /**
32 | * {@inheritdoc}
33 | */
34 | public function setValue($value)
35 | {
36 | $this->value = $value;
37 | }
38 |
39 | /**
40 | * {@inheritdoc}
41 | */
42 | public static function createFromType($type, array $settings = array())
43 | {
44 | switch ($type) {
45 | case self::TYPE_STRING:
46 | return new StringOption($settings);
47 |
48 | case self::TYPE_INTEGER:
49 | return new IntegerOption($settings);
50 |
51 | case self::TYPE_BOOLEAN:
52 | return new BooleanOption($settings);
53 | }
54 |
55 | return;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Model/Option/OptionInterface.php:
--------------------------------------------------------------------------------
1 | minRange = isset($settings['min']) ? $settings['min'] : 0;
20 | $this->maxRange = isset($settings['max']) ? $settings['max'] : 255;
21 | }
22 |
23 | /**
24 | * {@inheritdoc}
25 | */
26 | public function setValue($value)
27 | {
28 | if (!is_string($value)) {
29 | throw new InvalidArgumentException('String required');
30 | }
31 |
32 | $strlen = mb_strlen($value);
33 |
34 | if ($this->minRange > $strlen || $this->maxRange < $strlen) {
35 | throw new InvalidArgumentException('Invalid Value');
36 | }
37 |
38 | parent::setValue($value);
39 | }
40 |
41 | /**
42 | * {@inheritdoc}
43 | */
44 | public function getType()
45 | {
46 | return self::TYPE_STRING;
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Password Generator Library
2 |
3 | Simple library for generating random passwords.
4 |
5 | [](https://packagist.org/packages/hackzilla/password-generator)
6 | [](https://packagist.org/packages/hackzilla/password-generator)
7 | [](https://packagist.org/packages/hackzilla/password-generator)
8 | [](https://packagist.org/packages/hackzilla/password-generator)
9 |
10 |
11 | ## Requirements
12 |
13 | * PHP >= 8.0
14 | * ext-mbstring
15 |
16 | ## Installation
17 |
18 | Install Composer
19 |
20 | ```
21 | curl -sS https://getcomposer.org/installer | php
22 | mv composer.phar /usr/local/bin/composer
23 | ```
24 |
25 | Now tell composer to download the library by running the command:
26 |
27 | ``` bash
28 | $ composer require hackzilla/password-generator
29 | ```
30 |
31 | Composer will add the library to your composer.json file and install it into your project's `vendor/hackzilla` directory.
32 |
33 |
34 | ## Simple Usage
35 |
36 | ```php
37 | use Hackzilla\PasswordGenerator\Generator\ComputerPasswordGenerator;
38 |
39 | $generator = new ComputerPasswordGenerator();
40 |
41 | $generator
42 | ->setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, true)
43 | ->setOptionValue(ComputerPasswordGenerator::OPTION_LOWER_CASE, true)
44 | ->setOptionValue(ComputerPasswordGenerator::OPTION_NUMBERS, true)
45 | ->setOptionValue(ComputerPasswordGenerator::OPTION_SYMBOLS, false)
46 | ;
47 |
48 | $password = $generator->generatePassword();
49 | ```
50 |
51 |
52 | ## More Passwords Usage
53 |
54 | If you want to generate 10 passwords that are 12 characters long.
55 |
56 | ```php
57 | use Hackzilla\PasswordGenerator\Generator\ComputerPasswordGenerator;
58 |
59 | $generator = new ComputerPasswordGenerator();
60 |
61 | $generator
62 | ->setUppercase()
63 | ->setLowercase()
64 | ->setNumbers()
65 | ->setSymbols(false)
66 | ->setLength(12);
67 |
68 | $password = $generator->generatePasswords(10);
69 | ```
70 |
71 | ## Hybrid Password Generator Usage
72 |
73 | ```php
74 | use Hackzilla\PasswordGenerator\Generator\HybridPasswordGenerator;
75 |
76 | $generator = new HybridPasswordGenerator();
77 |
78 | $generator
79 | ->setUppercase()
80 | ->setLowercase()
81 | ->setNumbers()
82 | ->setSymbols(false)
83 | ->setSegmentLength(3)
84 | ->setSegmentCount(4)
85 | ->setSegmentSeparator('-');
86 |
87 | $password = $generator->generatePasswords(10);
88 | ```
89 |
90 | If you can think of a better name for this password generator then let me know.
91 |
92 | The segment separator will be remove from the possible characters.
93 |
94 |
95 | ## Human Password Generator Usage
96 |
97 | ```php
98 | use Hackzilla\PasswordGenerator\Generator\HumanPasswordGenerator;
99 |
100 | $generator = new HumanPasswordGenerator();
101 |
102 | $generator
103 | ->setWordList('/usr/share/dict/words')
104 | ->setWordCount(3)
105 | ->setWordSeparator('-');
106 |
107 | $password = $generator->generatePasswords(10);
108 | ```
109 |
110 | ## Requirement Password Generator Usage
111 |
112 | ```php
113 | use Hackzilla\PasswordGenerator\Generator\RequirementPasswordGenerator;
114 |
115 | $generator = new RequirementPasswordGenerator();
116 |
117 | $generator
118 | ->setLength(16)
119 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
120 | ->setOptionValue(RequirementPasswordGenerator::OPTION_LOWER_CASE, true)
121 | ->setOptionValue(RequirementPasswordGenerator::OPTION_NUMBERS, true)
122 | ->setOptionValue(RequirementPasswordGenerator::OPTION_SYMBOLS, true)
123 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 2)
124 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_LOWER_CASE, 2)
125 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_NUMBERS, 2)
126 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_SYMBOLS, 2)
127 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 8)
128 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_LOWER_CASE, 8)
129 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_NUMBERS, 8)
130 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_SYMBOLS, 8)
131 | ;
132 |
133 | $password = $generator->generatePassword();
134 | ```
135 |
136 | A limit can be removed by passing ```null```
137 |
138 | ```php
139 | $generator
140 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, null)
141 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, null)
142 | ;
143 | ```
144 |
145 | When setting the minimum and maximum values, be careful of unachievable settings.
146 |
147 | For example the following will end up in an infinite loop.
148 | ```php
149 | $generator
150 | ->setLength(4)
151 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
152 | ->setOptionValue(RequirementPasswordGenerator::OPTION_LOWER_CASE, false)
153 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 5)
154 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_LOWER_CASE, 1)
155 | ;
156 | ```
157 |
158 | For the moment you can call ```$generator->validLimits()``` to test whether the counts will cause problems.
159 | If the method returns true, then you can proceed. If false, then generatePassword() will likely cause an infinite loop.
160 |
161 | ## Example Implementations
162 |
163 | * Password Generator App [https://github.com/hackzilla/password-generator-app]
164 | * Password Generator Bundle [https://github.com/hackzilla/password-generator-bundle]
165 |
166 | ## Random Note
167 |
168 | Since version 1.5.0, the library depends on the presence of [random_int](http://www.php.net/random_int) which is found in PHP 7.0+
169 |
170 | ## Contributions and Issues
171 | See all contributors on [GitHub](https://github.com/hackzilla/password-generator/graphs/contributors).
172 |
173 | Please report issues using GitHub's issue tracker: [GitHub Repo](https://github.com/hackzilla/password-generator)
174 |
175 | If you find this project useful, consider [buying me a coffee](https://www.buymeacoffee.com/hackzilla).
176 |
177 | ## License
178 |
179 | This bundle is released under the MIT license. See the [LICENSE](https://github.com/hackzilla/password-generator/blob/main/LICENSE) file for details.
180 |
--------------------------------------------------------------------------------
/RandomGenerator/NoRandomGenerator.php:
--------------------------------------------------------------------------------
1 | setOption(self::OPTION_TEST_BOOLEAN, array('type' => Option::TYPE_BOOLEAN))
20 | ->setOption(self::OPTION_TEST_INTEGER, array('type' => Option::TYPE_INTEGER, 'min' => -100, 'max' => 100))
21 | ->setOption(self::OPTION_TEST_INTEGER_DEFAULT, array('type' => Option::TYPE_INTEGER, 'default' => 99))
22 | ->setOption(self::OPTION_TEST_STRING, array('type' => Option::TYPE_STRING, 'min' => 1, 'max' => 3, 'default' => ''))
23 | ->setOption(self::OPTION_TEST_STRING_DEFAULT, array('type' => Option::TYPE_STRING, 'default' => 'test'));
24 | }
25 |
26 | public function generatePassword()
27 | {
28 | return '';
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Tests/Generator/AbstractPasswordGeneratorTest.php:
--------------------------------------------------------------------------------
1 | _object = new AbstractPasswordGeneratorClass();
12 | }
13 |
14 | /**
15 | * @dataProvider generatePasswordsProvider
16 | *
17 | * @param $passwordCount
18 | */
19 | public function testGeneratePasswordsException($passwordCount): void
20 | {
21 | $this->expectException(\InvalidArgumentException::class);
22 | $this->_object->generatePasswords($passwordCount);
23 | }
24 |
25 | public function generatePasswordsProvider()
26 | {
27 | return array(
28 | array(''),
29 | array(null),
30 | array(-1),
31 | array(0.1),
32 | array(true),
33 | );
34 | }
35 |
36 | /**
37 | * @dataProvider lengthProvider
38 | *
39 | * @param $count
40 | */
41 | public function testGeneratePasswords($count): void
42 | {
43 | $passwords = $this->_object->generatePasswords($count);
44 |
45 | $this->assertSame(\count($passwords), $count);
46 | }
47 |
48 | /**
49 | * @return array
50 | */
51 | public function lengthProvider()
52 | {
53 | return array(
54 | array(1),
55 | array(4),
56 | array(8),
57 | array(16),
58 | );
59 | }
60 |
61 | /**
62 | * @dataProvider optionProvider
63 | *
64 | * @param string $option
65 | */
66 | public function testGetOption($option): void
67 | {
68 | $this->assertInstanceOf('Hackzilla\PasswordGenerator\Model\Option\OptionInterface', $this->_object->getOption($option));
69 | }
70 |
71 | public function optionProvider()
72 | {
73 | return array(
74 | array(AbstractPasswordGeneratorClass::OPTION_TEST_BOOLEAN),
75 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER),
76 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER_DEFAULT),
77 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING),
78 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING_DEFAULT),
79 | );
80 | }
81 |
82 | public function testGetPossibleOptions(): void
83 | {
84 | $this->assertTrue(is_array($this->_object->getOptions()));
85 | $this->assertSame(count($this->_object->getOptions()), 5);
86 | }
87 |
88 | public function testGetOptionValueDefault(): void
89 | {
90 | $this->assertSame(99, $this->_object->getOptionValue(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER_DEFAULT));
91 | $this->assertSame('test', $this->_object->getOptionValue(AbstractPasswordGeneratorClass::OPTION_TEST_STRING_DEFAULT));
92 | }
93 |
94 | /**
95 | * @dataProvider setOptionValueProvider
96 | *
97 | * @param $option
98 | * @param $value
99 | */
100 | public function testSetOptionValue($option, $value): void
101 | {
102 | $this->_object->setOptionValue($option, $value);
103 | $this->assertSame($this->_object->getOptionValue($option), $value);
104 | }
105 |
106 | /**
107 | * @return array
108 | */
109 | public function setOptionValueProvider()
110 | {
111 | return array(
112 | array(AbstractPasswordGeneratorClass::OPTION_TEST_BOOLEAN, true),
113 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, 0),
114 | );
115 | }
116 |
117 | /**
118 | * @dataProvider setOptionExceptionProvider
119 | *
120 | * @param $option
121 | * @param $value
122 | */
123 | public function testSetExceptionOption($option, $value): void
124 | {
125 | $this->expectException(\InvalidArgumentException::class);
126 | $this->_object->setOptionValue($option, $value);
127 | }
128 |
129 | /**
130 | * @return array
131 | */
132 | public function setOptionExceptionProvider()
133 | {
134 | return array(
135 | array(AbstractPasswordGeneratorClass::OPTION_TEST_BOOLEAN, 99),
136 | array(AbstractPasswordGeneratorClass::OPTION_TEST_BOOLEAN, null),
137 | array(AbstractPasswordGeneratorClass::OPTION_TEST_BOOLEAN, 'test'),
138 |
139 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, true),
140 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, null),
141 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, 'test'),
142 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, -101),
143 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, 101),
144 | );
145 | }
146 |
147 | public function testUnknownSetOption(): void
148 | {
149 | $this->expectException(\InvalidArgumentException::class);
150 | $this->_object->setOption('unknown', array());
151 | }
152 |
153 | public function testUnknownOption(): void
154 | {
155 | $this->assertNull($this->_object->getOption('unknown', array()));
156 | }
157 |
158 | public function testUnknownSetOptionValue(): void
159 | {
160 | $this->expectException(\InvalidArgumentException::class);
161 | $this->_object->setOptionValue('unknown', true);
162 | }
163 |
164 | public function testUnknownOptionValue(): void
165 | {
166 | $this->expectException(\InvalidArgumentException::class);
167 | $this->_object->getOptionValue('unknown', true);
168 | }
169 |
170 | public function testUnknownParameter(): void
171 | {
172 | $this->assertNull($this->_object->getParameter('unknown'));
173 | }
174 |
175 | /**
176 | * @dataProvider parameterProvider
177 | *
178 | * @param $parameter
179 | * @param $value
180 | */
181 | public function testParameter($parameter, $value): void
182 | {
183 | $this->_object->setParameter($parameter, $value);
184 |
185 | $this->assertSame($value, $this->_object->getParameter($parameter));
186 | }
187 |
188 | public function parameterProvider()
189 | {
190 | return array(
191 | array('a', 1),
192 | array('ab', null),
193 | array('test', true),
194 | array('test2', 'value'),
195 | );
196 | }
197 |
198 | /**
199 | * @dataProvider validateValueProvider
200 | *
201 | * @param $option
202 | * @param $value
203 | * @param $return
204 | */
205 | public function testValidateValue($option, $value, $return): void
206 | {
207 | if (!$return) {
208 | $this->expectException('\InvalidArgumentException');
209 | }
210 |
211 | $this->_object->setOptionValue($option, $value);
212 |
213 | if ($return) {
214 | $this->assertSame($value, $this->_object->getOptionValue($option));
215 | }
216 | }
217 |
218 | /**
219 | * @return array
220 | */
221 | public function validateValueProvider()
222 | {
223 | return array(
224 | array(AbstractPasswordGeneratorClass::OPTION_TEST_BOOLEAN, true, true),
225 | array(AbstractPasswordGeneratorClass::OPTION_TEST_BOOLEAN, 1, false),
226 | array(AbstractPasswordGeneratorClass::OPTION_TEST_BOOLEAN, null, false),
227 |
228 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, 0, true),
229 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, 100, true),
230 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, -100, true),
231 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, true, false),
232 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, null, false),
233 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER, '', false),
234 |
235 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER_DEFAULT, 2147483647, true),
236 | array(AbstractPasswordGeneratorClass::OPTION_TEST_INTEGER_DEFAULT, -2147483648, true),
237 |
238 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING, 'abc', true),
239 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING, 'a', true),
240 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING, '', false),
241 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING, 0, false),
242 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING, null, false),
243 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING, true, false),
244 |
245 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING, 'ac', true),
246 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING, 'abcd', false),
247 | array(AbstractPasswordGeneratorClass::OPTION_TEST_STRING, '', false),
248 |
249 | array('fail', '', false),
250 | );
251 | }
252 | }
253 |
--------------------------------------------------------------------------------
/Tests/Generator/ComputerPasswordGeneratorTest.php:
--------------------------------------------------------------------------------
1 | _object = new ComputerPasswordGenerator();
18 |
19 | $this->_object
20 | ->setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, false)
21 | ->setOptionValue(ComputerPasswordGenerator::OPTION_LOWER_CASE, false)
22 | ->setOptionValue(ComputerPasswordGenerator::OPTION_NUMBERS, false)
23 | ->setOptionValue(ComputerPasswordGenerator::OPTION_SYMBOLS, false)
24 | ->setOptionValue(ComputerPasswordGenerator::OPTION_AVOID_SIMILAR, false);
25 | }
26 |
27 | /**
28 | * @dataProvider lengthProvider
29 | *
30 | * @param $length
31 | */
32 | public function testLength($length): void
33 | {
34 | $this->_object->setLength($length);
35 | $this->assertSame($this->_object->getLength(), $length);
36 | }
37 |
38 | /**
39 | * @dataProvider lengthProvider
40 | *
41 | * @param $length
42 | */
43 | public function testGeneratePassword($length): void
44 | {
45 | $this->_object
46 | ->setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, true)
47 | ->setOptionValue(ComputerPasswordGenerator::OPTION_LOWER_CASE, true)
48 | ->setOptionValue(ComputerPasswordGenerator::OPTION_NUMBERS, true)
49 | ->setOptionValue(ComputerPasswordGenerator::OPTION_SYMBOLS, true)
50 | ->setOptionValue(ComputerPasswordGenerator::OPTION_AVOID_SIMILAR, true);
51 |
52 | $this->_object->setLength($length);
53 | $this->assertSame(\mb_strlen($this->_object->generatePassword()), $length);
54 | }
55 |
56 | /**
57 | * @dataProvider lengthProvider
58 | *
59 | * @param $length
60 | */
61 | public function testGenerateMultiBytePassword($length): void
62 | {
63 | $this->_object
64 | ->setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, true)
65 | ->setOptionValue(ComputerPasswordGenerator::OPTION_LOWER_CASE, true)
66 | ->setParameter(ComputerPasswordGenerator::PARAMETER_UPPER_CASE, 'ßAÄÖÜÉÑÇŠŽДЖЮИЫ')
67 | ->setParameter(ComputerPasswordGenerator::PARAMETER_LOWER_CASE, 'ßaäöüéñçšžджюиы')
68 | ;
69 |
70 | $this->_object->setLength($length);
71 | $generatedPassword = $this->_object->generatePassword();
72 |
73 | $this->assertSame(\mb_strlen($generatedPassword), $length);
74 |
75 | $uppercase = $this->_object->getParameter(ComputerPasswordGenerator::PARAMETER_UPPER_CASE);
76 | $lowercase = $this->_object->getParameter(ComputerPasswordGenerator::PARAMETER_LOWER_CASE);
77 |
78 | // Check each character in the generated password
79 | foreach (mb_str_split($generatedPassword) as $char) {
80 | $this->assertTrue(mb_strpos($uppercase, $char) !== false || mb_strpos($lowercase, $char) !== false, "Character '{$char}' is not in the allowed character sets");
81 | }
82 | }
83 |
84 | /**
85 | * @return array
86 | */
87 | public function lengthProvider()
88 | {
89 | return array(
90 | array(1),
91 | array(4),
92 | array(8),
93 | array(16),
94 | );
95 | }
96 |
97 | /**
98 | * @dataProvider getterSetterProvider
99 | *
100 | * @param $method
101 | */
102 | public function testGetterSetters($method): void
103 | {
104 | $this->_object->{'set'.$method}(true);
105 | $this->assertTrue($this->_object->{'get'.$method}());
106 |
107 | $this->_object->{'set'.$method}(false);
108 | $this->assertTrue(!$this->_object->{'get'.$method}());
109 | }
110 |
111 | /**
112 | * @dataProvider lengthExceptionProvider
113 | *
114 | * @param $param
115 | */
116 | public function testLengthException($param): void
117 | {
118 | $this->expectException(\InvalidArgumentException::class);
119 | $this->_object->setLength($param);
120 | }
121 |
122 | public function lengthExceptionProvider()
123 | {
124 | return array(
125 | array('a'),
126 | array(false),
127 | array(null),
128 | array(-1),
129 | );
130 | }
131 |
132 | /**
133 | * @dataProvider getterSetterProvider
134 | *
135 | * @param $method
136 | */
137 | public function testGetterSettersException($method): void
138 | {
139 | $this->expectException(\InvalidArgumentException::class);
140 | $this->_object->{'set'.$method}(1);
141 | }
142 |
143 | public function getterSetterProvider()
144 | {
145 | return array(
146 | array('Uppercase'),
147 | array('Lowercase'),
148 | array('Numbers'),
149 | array('Symbols'),
150 | array('AvoidSimilar'),
151 | );
152 | }
153 |
154 | /**
155 | * @dataProvider optionProvider
156 | *
157 | * @param $option
158 | * @param $exists
159 | * @param $dontExist
160 | */
161 | public function testSetOption($option, $exists, $dontExist): void
162 | {
163 | $this->_object->setOptionValue($option, true);
164 | $availableCharacters = $this->_object->getCharacterList()->getCharacters();
165 |
166 | foreach ($exists as $check) {
167 | $this->assertStringContainsString($check, $availableCharacters);
168 | }
169 | foreach ($dontExist as $check) {
170 | $this->assertStringNotContainsString($check, $availableCharacters);
171 | }
172 | }
173 |
174 | /**
175 | * @return array
176 | */
177 | public function optionProvider()
178 | {
179 | return array(
180 | array(ComputerPasswordGenerator::OPTION_UPPER_CASE, array('A', 'B', 'C'), array('a', 'b', 'c')),
181 | array(ComputerPasswordGenerator::OPTION_LOWER_CASE, array('a', 'b', 'c'), array('A', 'B', 'C')),
182 | array(ComputerPasswordGenerator::OPTION_NUMBERS, array('1', '2', '3'), array('a', 'b', 'c', 'A', 'B', 'C')),
183 | array(ComputerPasswordGenerator::OPTION_SYMBOLS, array('+', '=', '?'), array('a', 'b', 'c', 'A', 'B', 'C')),
184 | );
185 | }
186 |
187 | public function testSetOptionSimilar(): void
188 | {
189 | $exists = array('a', 'b', 'c', 'A', 'B', 'C');
190 | $dontExist = array('o', 'l', 'O');
191 |
192 | $this->_object
193 | ->setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, true)
194 | ->setOptionValue(ComputerPasswordGenerator::OPTION_LOWER_CASE, true)
195 | ->setOptionValue(ComputerPasswordGenerator::OPTION_AVOID_SIMILAR, true);
196 |
197 | $availableCharacters = $this->_object->getCharacterList()->getCharacters();
198 |
199 | foreach ($exists as $check) {
200 | $this->assertStringContainsString($check, $availableCharacters);
201 | }
202 | foreach ($dontExist as $check) {
203 | $this->assertStringNotContainsString($check, $availableCharacters);
204 | }
205 | }
206 |
207 | /**
208 | * @dataProvider optionsProvider
209 | *
210 | * @param $option
211 | * @param $parameter
212 | */
213 | public function testSetGet($option, $parameter): void
214 | {
215 | $this->_object
216 | ->setOptionValue($option, true)
217 | ->setParameter($parameter, 'A')
218 | ->setLength(4);
219 |
220 | $this->assertSame('AAAA', $this->_object->generatePassword());
221 | }
222 |
223 | /**
224 | * @return array
225 | */
226 | public function optionsProvider()
227 | {
228 | return array(
229 | array(ComputerPasswordGenerator::OPTION_UPPER_CASE, ComputerPasswordGenerator::PARAMETER_UPPER_CASE),
230 | array(ComputerPasswordGenerator::OPTION_LOWER_CASE, ComputerPasswordGenerator::PARAMETER_LOWER_CASE),
231 | array(ComputerPasswordGenerator::OPTION_NUMBERS, ComputerPasswordGenerator::PARAMETER_NUMBERS),
232 | array(ComputerPasswordGenerator::OPTION_SYMBOLS, ComputerPasswordGenerator::PARAMETER_SYMBOLS),
233 | );
234 | }
235 |
236 | /**
237 | *
238 | */
239 | public function testAvoidSimilar(): void
240 | {
241 | $this->_object
242 | ->setParameter(ComputerPasswordGenerator::PARAMETER_UPPER_CASE, 'AB')
243 | ->setParameter(ComputerPasswordGenerator::PARAMETER_SIMILAR, 'B')
244 | ->setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, true)
245 | ->setOptionValue(ComputerPasswordGenerator::OPTION_AVOID_SIMILAR, true);
246 |
247 | $this->_object->setLength(4);
248 |
249 | $this->assertSame('AAAA', $this->_object->generatePassword());
250 | }
251 |
252 | /**
253 | *
254 | */
255 | public function testCharacterListException(): void
256 | {
257 | $this->expectException(CharactersNotFoundException::class);
258 | $this->_object->getCharacterList();
259 | }
260 | }
261 |
--------------------------------------------------------------------------------
/Tests/Generator/Data/WordList/empty.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hackzilla/password-generator/743c8493d2c33ebf9496a1c3c248efeb568fe134/Tests/Generator/Data/WordList/empty.txt
--------------------------------------------------------------------------------
/Tests/Generator/Data/WordList/simple.txt:
--------------------------------------------------------------------------------
1 | blancmange
2 | blancmange
3 | blancmange
4 | blancmange
5 | blancmange
6 | blancmange
7 | blancmange
8 |
--------------------------------------------------------------------------------
/Tests/Generator/DummyPasswordGeneratorTest.php:
--------------------------------------------------------------------------------
1 | _object = new DummyPasswordGenerator();
17 | }
18 |
19 | /**
20 | * @dataProvider lengthProvider
21 | *
22 | * @param $length
23 | * @param $comparePassword
24 | */
25 | public function testGeneratePasswords($length, $comparePassword): void
26 | {
27 | $this->_object->setOptionValue(DummyPasswordGenerator::OPTION_LENGTH, $length);
28 | $passwords = $this->_object->generatePasswords($length);
29 |
30 | $this->assertSame(count($passwords), $length);
31 |
32 | foreach ($passwords as $password) {
33 | $this->assertSame($password, $comparePassword);
34 | }
35 | }
36 |
37 | /**
38 | * @dataProvider lengthProvider
39 | *
40 | * @param $length
41 | * @param $password
42 | */
43 | public function testGeneratePassword($length, $password)
44 | {
45 | $this->_object->setOptionValue(DummyPasswordGenerator::OPTION_LENGTH, $length);
46 | $this->assertSame($this->_object->generatePassword(), $password);
47 | }
48 |
49 | /**
50 | * @dataProvider lengthProvider
51 | *
52 | * @param $length
53 | */
54 | public function testLength($length): void
55 | {
56 | $this->_object->setLength($length);
57 | $this->assertSame($this->_object->getLength(), $length);
58 | }
59 |
60 | /**
61 | * @return array
62 | */
63 | public function lengthProvider()
64 | {
65 | return array(
66 | array(1, 'p'),
67 | array(4, 'pass'),
68 | array(8, 'password'),
69 | array(16, 'password????????'),
70 | );
71 | }
72 |
73 | /**
74 | * @dataProvider lengthExceptionProvider
75 | *
76 | * @param $param
77 | */
78 | public function testLengthException($param): void
79 | {
80 | $this->expectException(\InvalidArgumentException::class);
81 | $this->_object->setLength($param);
82 | }
83 |
84 | public function lengthExceptionProvider()
85 | {
86 | return array(
87 | array('a'),
88 | array(false),
89 | array(null),
90 | array(-1),
91 | );
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/Tests/Generator/HumanPasswordGeneratorClass.php:
--------------------------------------------------------------------------------
1 | _object = new HumanPasswordGenerator();
17 | $this->_object->setWordSeparator('');
18 | }
19 |
20 | /**
21 | *
22 | */
23 | public function testWordCount(): void
24 | {
25 | $this->_object->setWordCount(1);
26 | $this->assertSame($this->_object->getWordCount(), 1);
27 |
28 | $this->_object->setWordCount(6);
29 | $this->assertSame($this->_object->getWordCount(), 6);
30 |
31 | $this->expectException('InvalidArgumentException');
32 | $this->_object->setWordCount(-6);
33 |
34 | $this->expectException('InvalidArgumentException');
35 | $this->_object->setWordCount('fail');
36 | }
37 |
38 | /**
39 | *
40 | */
41 | public function testMinWordLength(): void
42 | {
43 | $this->_object->setMinWordLength(1);
44 | $this->assertSame($this->_object->getMinWordLength(), 1);
45 |
46 | $this->_object->setMinWordLength(6);
47 | $this->assertSame($this->_object->getMinWordLength(), 6);
48 |
49 | $this->expectException('InvalidArgumentException');
50 | $this->_object->setMinWordLength(-6);
51 |
52 | $this->expectException('InvalidArgumentException');
53 | $this->_object->setMinWordLength('fail');
54 | }
55 |
56 | /**
57 | *
58 | */
59 | public function testMaxWordLength(): void
60 | {
61 | $this->_object->setMaxWordLength(1);
62 | $this->assertSame($this->_object->getMaxWordLength(), 1);
63 |
64 | $this->_object->setMaxWordLength(6);
65 | $this->assertSame($this->_object->getMaxWordLength(), 6);
66 |
67 | $this->expectException('InvalidArgumentException');
68 | $this->_object->setMaxWordLength(-6);
69 |
70 | $this->expectException('InvalidArgumentException');
71 | $this->_object->setMaxWordLength('fail');
72 | }
73 |
74 | /**
75 | *
76 | */
77 | public function testWordSeparator(): void
78 | {
79 | $this->_object->setWordSeparator('');
80 | $this->assertSame($this->_object->getWordSeparator(), '');
81 |
82 | $this->_object->setWordSeparator('-');
83 | $this->assertSame($this->_object->getWordSeparator(), '-');
84 |
85 | $this->_object->setWordSeparator('-?*');
86 | $this->assertSame($this->_object->getWordSeparator(), '-?*');
87 |
88 | $this->expectException('InvalidArgumentException');
89 | $this->_object->setWordSeparator(-6);
90 |
91 | $this->expectException('InvalidArgumentException');
92 | $this->_object->setMaxWordLength(null);
93 | }
94 |
95 | /**
96 | * @return string
97 | */
98 | public function getSimpleWordList()
99 | {
100 | $reflClass = new \ReflectionClass(get_class($this));
101 | $filename = dirname($reflClass->getFileName()).DIRECTORY_SEPARATOR.'Data'.DIRECTORY_SEPARATOR.'WordList'.DIRECTORY_SEPARATOR.'simple.txt';
102 |
103 | return $filename;
104 | }
105 |
106 | /**
107 | * @return string
108 | */
109 | public function getEmptyWordList()
110 | {
111 | $reflClass = new \ReflectionClass(get_class($this));
112 | $filename = dirname($reflClass->getFileName()).DIRECTORY_SEPARATOR.'Data'.DIRECTORY_SEPARATOR.'WordList'.DIRECTORY_SEPARATOR.'empty.txt';
113 |
114 | return $filename;
115 | }
116 |
117 | /**
118 | *
119 | */
120 | public function testWordList(): void
121 | {
122 | $filename = $this->getSimpleWordList();
123 |
124 | $this->_object->setWordList($filename);
125 | $this->assertSame($this->_object->getWordList(), $filename);
126 |
127 | $this->expectException('InvalidArgumentException');
128 | $this->_object->setWordList(7);
129 | }
130 |
131 | public function testWordListException()
132 | {
133 | $this->expectException(\Hackzilla\PasswordGenerator\Exception\WordsNotFoundException::class);
134 | $filename = $this->getEmptyWordList();
135 |
136 | $this->_object->setWordList($filename);
137 | $this->_object->generatePassword();
138 | }
139 |
140 | public function testUnknownWordList(): void
141 | {
142 | $this->expectException(\Hackzilla\PasswordGenerator\Exception\FileNotFoundException::class);
143 | $this->_object->setWordList('fail');
144 | }
145 |
146 | public function testGenerateWordList(): void
147 | {
148 | $filename = $this->getSimpleWordList();
149 |
150 | $this->_object->setWordList($filename);
151 | $words = $this->_object->generateWordList();
152 |
153 | $this->assertSame(count($words), 7);
154 | $this->assertSame($words[0], 'blancmange');
155 | }
156 |
157 | /**
158 | * @dataProvider lengthProvider
159 | *
160 | * @param $length
161 | */
162 | public function testGeneratePasswords($length): void
163 | {
164 | $filename = $this->getSimpleWordList();
165 |
166 | $this->_object->setWordList($filename);
167 | $this->_object->setWordCount($length);
168 | $passwords = $this->_object->generatePasswords($length);
169 |
170 | $this->assertSame(count($passwords), $length);
171 |
172 | foreach ($passwords as $password) {
173 | $this->assertSame($password, \str_repeat('blancmange', $length));
174 | }
175 | }
176 |
177 | /**
178 | * @dataProvider lengthProvider
179 | *
180 | * @param $length
181 | */
182 | public function testGeneratePassword($length): void
183 | {
184 | $filename = $this->getSimpleWordList();
185 |
186 | $this->_object->setWordList($filename);
187 | $this->_object->setWordCount($length);
188 | $this->assertSame($this->_object->generatePassword(), \str_repeat('blancmange', $length));
189 | }
190 |
191 | public function testGeneratePasswordException(): void
192 | {
193 | $this->expectException('\Hackzilla\PasswordGenerator\Exception\FileNotFoundException');
194 | $this->_object->generatePassword();
195 | }
196 |
197 | public function testGeneratePasswordImpossiblePasswordLengthException(): void
198 | {
199 | $this->expectException(\Hackzilla\PasswordGenerator\Exception\ImpossiblePasswordLengthException::class);
200 |
201 | $this->_object->setLength(20);
202 | $this->_object->setWordCount(3);
203 | $this->_object->setMinWordLength(10);
204 | $this->_object->setMaxWordLength(10);
205 |
206 | $filename = $this->getSimpleWordList();
207 | $this->_object->setWordList($filename);
208 |
209 | $this->_object->generatePassword();
210 | }
211 |
212 | public function testRandomWord(): void
213 | {
214 | $filename = $this->getSimpleWordList();
215 | $this->_object->setWordList($filename);
216 |
217 | $this->assertEquals('blancmange', $this->_object->randomWord(5, 15));
218 | }
219 |
220 | public function testRandomWordException(): void
221 | {
222 | $this->expectException(\Hackzilla\PasswordGenerator\Exception\NotEnoughWordsException::class);
223 |
224 | $filename = $this->getSimpleWordList();
225 | $this->_object->setWordList($filename);
226 |
227 | $this->_object->randomWord(12, 15);
228 | }
229 |
230 | public function testEmptyException(): void
231 | {
232 | $this->expectException(\Hackzilla\PasswordGenerator\Exception\WordsNotFoundException::class);
233 | $generator = new HumanPasswordGeneratorClass();
234 |
235 | $generator->generatePassword();
236 | }
237 |
238 | public function testGetPasswordLength(): void
239 | {
240 | $this->_object->setLength(1);
241 | $this->_object->setWordCount(3);
242 | $this->_object->setMinWordLength(3);
243 | $this->_object->setMaxWordLength(6);
244 | $this->_object->setWordSeparator('-');
245 |
246 | $this->assertEquals(11, $this->_object->getMinPasswordLength());
247 | $this->assertEquals(20, $this->_object->getMaxPasswordLength());
248 | }
249 |
250 | /**
251 | * @dataProvider lengthProvider
252 | *
253 | * @param $length
254 | */
255 | public function testGeneratePasswordWithSeparator($length): void
256 | {
257 | $filename = $this->getSimpleWordList();
258 |
259 | $this->_object->setWordList($filename);
260 | $this->_object->setWordCount($length);
261 | $this->_object->setWordSeparator('-');
262 | $this->assertSame($this->_object->generatePassword(), $this->makePassword('blancmange', $length, '-'));
263 | }
264 |
265 | /**
266 | * @param $word
267 | * @param $length
268 | * @param $separator
269 | *
270 | * @return string
271 | */
272 | private function makePassword($word, $length, $separator)
273 | {
274 | $password = '';
275 |
276 | for ($i = 0; $i < $length; ++$i) {
277 | if ($i) {
278 | $password .= $separator;
279 | }
280 |
281 | $password .= $word;
282 | }
283 |
284 | return $password;
285 | }
286 |
287 | /**
288 | * @return array
289 | */
290 | public function lengthProvider()
291 | {
292 | return array(
293 | array(1),
294 | array(4),
295 | array(8),
296 | array(16),
297 | );
298 | }
299 |
300 | /**
301 | * @dataProvider lengthExceptionProvider
302 | */
303 | public function testLengthException($length): void
304 | {
305 | $this->expectException(\InvalidArgumentException::class);
306 | $this->_object->setLength($length);
307 | }
308 |
309 | /**
310 | * @return array
311 | */
312 | public function lengthExceptionProvider()
313 | {
314 | return array(
315 | array(null),
316 | array('A'),
317 | array(-1),
318 | );
319 | }
320 | /**
321 | * @dataProvider fixedPasswordsProvider
322 | * @param $length
323 | */
324 | public function testGeneratePasswordFixedLength($length): void
325 | {
326 | $this->_object->setMinWordLength(1);
327 | $this->_object->setMaxWordLength(10);
328 |
329 | $this->_object->setParameter(HumanPasswordGenerator::PARAMETER_WORD_CACHE, array(
330 | 'a',
331 | 'ab',
332 | 'abc',
333 | 'abcd',
334 | 'abcde',
335 | 'abcdef',
336 | 'abcdefg',
337 | 'abcdefgh',
338 | 'abcdefghi',
339 | 'abcdefghij',
340 | 'abcdefghijk',
341 | 'abcdefghijkl',
342 | 'abcdefghijklm',
343 | 'abcdefghijklmn',
344 | 'abcdefghijklmno',
345 | 'abcdefghijklmnop',
346 | ));
347 |
348 | $this->_object->setLength($length);
349 | $this->_object->setWordCount(3);
350 | $this->_object->setWordSeparator('-');
351 |
352 | $this->assertEquals($length, \mb_strlen($this->_object->generatePassword()));
353 | }
354 |
355 | public function fixedPasswordsProvider()
356 | {
357 | return array(
358 | array(5),
359 | array(10),
360 | array(20),
361 | array(30),
362 | array(32),
363 | );
364 | }
365 | }
366 |
--------------------------------------------------------------------------------
/Tests/Generator/HybridPasswordGeneratorTest.php:
--------------------------------------------------------------------------------
1 | _object = new HybridPasswordGenerator();
14 |
15 | $this->_object
16 | ->setOptionValue(HybridPasswordGenerator::OPTION_UPPER_CASE, false)
17 | ->setOptionValue(HybridPasswordGenerator::OPTION_LOWER_CASE, false)
18 | ->setOptionValue(HybridPasswordGenerator::OPTION_NUMBERS, false)
19 | ->setOptionValue(HybridPasswordGenerator::OPTION_SYMBOLS, false)
20 | ->setOptionValue(HybridPasswordGenerator::OPTION_AVOID_SIMILAR, false);
21 | }
22 |
23 | public function passwordProvider()
24 | {
25 | return array(
26 | array(3, 4, '-', '/[A-Za-z0-9]{3}\-[A-Za-z0-9]{3}\-[A-Za-z0-9]{3}\-[A-Za-z0-9]{3}/'),
27 | array(1, 1, '-', '/[A-Za-z0-9]{1}/'),
28 | array(1, 2, '', '/[A-Za-z0-9]{1}[A-Za-z0-9]{1}/'),
29 | array(3, 2, '*', '/[A-Za-z0-9]{3}\*[A-Za-z0-9]{3}/'),
30 | );
31 | }
32 |
33 | /**
34 | * @dataProvider passwordProvider
35 | *
36 | * @param $segmentLength
37 | * @param $segmentCount
38 | * @param $segmentSeparator
39 | * @param $regExp
40 | */
41 | public function testGeneratePassword($segmentLength, $segmentCount, $segmentSeparator, $regExp): void
42 | {
43 | $this->_object
44 | ->setOptionValue(HybridPasswordGenerator::OPTION_UPPER_CASE, true)
45 | ->setOptionValue(HybridPasswordGenerator::OPTION_LOWER_CASE, true)
46 | ->setOptionValue(HybridPasswordGenerator::OPTION_NUMBERS, true)
47 | ->setOptionValue(HybridPasswordGenerator::OPTION_AVOID_SIMILAR, true);
48 |
49 | $this->_object->setSegmentLength($segmentLength);
50 | $this->_object->setSegmentCount($segmentCount);
51 | $this->_object->setSegmentSeparator($segmentSeparator);
52 |
53 | $this->assertMatchesRegularExpression($regExp, $this->_object->generatePassword());
54 | }
55 |
56 | /**
57 | * @dataProvider lengthProvider
58 | *
59 | * @param $count
60 | */
61 | public function testSetSegmentCount($count): void
62 | {
63 | $this->_object->setSegmentCount($count);
64 | $this->assertSame($this->_object->getSegmentCount(), $count);
65 | $this->assertSame($this->_object->getLength(), $count);
66 | }
67 |
68 | public function testSetSegmentCountException(): void
69 | {
70 | $this->expectException(\InvalidArgumentException::class);
71 | $this->_object->setSegmentCount(-1);
72 | }
73 |
74 | /**
75 | * @dataProvider lengthProvider
76 | *
77 | * @param $length
78 | */
79 | public function testSetSegmentLength($length): void
80 | {
81 | $this->_object->setSegmentLength($length);
82 | $this->assertSame($this->_object->getSegmentLength(), $length);
83 | }
84 |
85 | public function testSetSegmentLengthException(): void
86 | {
87 | $this->expectException(\InvalidArgumentException::class);
88 | $this->_object->setSegmentLength(-1);
89 | }
90 |
91 | /**
92 | * @dataProvider lengthProvider
93 | *
94 | * @param $length
95 | */
96 | public function testSetLength($length): void
97 | {
98 | $this->_object->setLength($length);
99 | $this->assertSame($this->_object->getLength(), $length);
100 | }
101 |
102 | public function lengthProvider()
103 | {
104 | return array(
105 | array(1),
106 | array(4),
107 | array(8),
108 | array(16),
109 | );
110 | }
111 |
112 | /**
113 | * @dataProvider segmentProvider
114 | *
115 | * @param $separator
116 | */
117 | public function testSetSegmentSeparator($separator): void
118 | {
119 | $this->_object->setSegmentSeparator($separator);
120 | $this->assertSame($this->_object->getSegmentSeparator(), $separator);
121 | }
122 |
123 | public function segmentProvider()
124 | {
125 | return array(
126 | array(''),
127 | array('-'),
128 | );
129 | }
130 |
131 | public function testSetSegmentSeparatorException(): void
132 | {
133 | $this->expectException(\InvalidArgumentException::class);
134 | $this->_object->setSegmentSeparator(-1);
135 | }
136 |
137 | /**
138 | * @dataProvider optionsProvider
139 | *
140 | * @param $option
141 | * @param $parameter
142 | */
143 | public function testSetGet($option, $parameter): void
144 | {
145 | $this->_object
146 | ->setOptionValue($option, true)
147 | ->setParameter($parameter, 'A')
148 | ->setParameter(HybridPasswordGenerator::PARAMETER_SEPARATOR, '-')
149 | ->setSegmentLength(1)
150 | ->setSegmentCount(4)
151 | ;
152 |
153 | $this->assertSame('A-A-A-A', $this->_object->generatePassword());
154 | }
155 |
156 | /**
157 | * @return array
158 | */
159 | public function optionsProvider()
160 | {
161 | return array(
162 | array(HybridPasswordGenerator::OPTION_UPPER_CASE, HybridPasswordGenerator::PARAMETER_UPPER_CASE),
163 | array(HybridPasswordGenerator::OPTION_LOWER_CASE, HybridPasswordGenerator::PARAMETER_LOWER_CASE),
164 | array(HybridPasswordGenerator::OPTION_NUMBERS, HybridPasswordGenerator::PARAMETER_NUMBERS),
165 | array(HybridPasswordGenerator::OPTION_SYMBOLS, HybridPasswordGenerator::PARAMETER_SYMBOLS),
166 | );
167 | }
168 |
169 | public function testCharacterListException(): void
170 | {
171 | $this->expectException('\Hackzilla\PasswordGenerator\Exception\CharactersNotFoundException');
172 | $this->_object->getCharacterList();
173 | }
174 | }
175 |
--------------------------------------------------------------------------------
/Tests/Generator/PronounceablePasswordGeneratorTest.php:
--------------------------------------------------------------------------------
1 | _object = new PronounceablePasswordGenerator();
20 | }
21 |
22 | /**
23 | * @dataProvider passwordsProvider
24 | *
25 | * @param string $vowels
26 | * @param bool $upperCase
27 | * @param bool $symbols
28 | * @param bool $numbers
29 | */
30 | public function testGeneratePassword($vowels, $upperCase, $symbols, $numbers): void
31 | {
32 | $this->_object->setParameter(PronounceablePasswordGenerator::PARAMETER_VOWELS, $vowels);
33 | $this->_object->setOptionValue(ComputerPasswordGenerator::OPTION_LENGTH, 16);
34 | $this->_object->setOptionValue(ComputerPasswordGenerator::OPTION_LOWER_CASE, true);
35 | $this->_object->setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, $upperCase);
36 | $this->_object->setOptionValue(ComputerPasswordGenerator::OPTION_SYMBOLS, $symbols);
37 | $this->_object->setOptionValue(ComputerPasswordGenerator::OPTION_NUMBERS, $numbers);
38 |
39 | $passwords = $this->_object->generatePasswords(10);
40 | foreach ($passwords as $password) {
41 | $passwordLen = mb_strlen($password);
42 | $isLastCharVowel = null;
43 |
44 | for ($i = 0; $i < $passwordLen; $i++) {
45 | $char = $password[$i];
46 | $isVowel = false !== mb_stripos($vowels, $char);
47 | if (null !== $isLastCharVowel) {
48 | $this->assertNotEquals($isVowel, $isLastCharVowel);
49 | }
50 | $isLastCharVowel = $isVowel;
51 | }
52 | }
53 | }
54 |
55 | public function passwordsProvider()
56 | {
57 | return array(
58 | array('aeiou', true, true, true),
59 | array('aeiou', true, true, false),
60 | array('aeiou', true, false, true),
61 | array('aeiou', false, true, true),
62 | array('aeiou', false, true, false),
63 | array('aeiou', false, false, true),
64 | array('aeiou', false, false, false),
65 | );
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Tests/Generator/RequirementPasswordGeneratorTest.php:
--------------------------------------------------------------------------------
1 | _object = new RequirementPasswordGenerator();
19 |
20 | $this->_object
21 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, false)
22 | ->setOptionValue(RequirementPasswordGenerator::OPTION_LOWER_CASE, false)
23 | ->setOptionValue(RequirementPasswordGenerator::OPTION_NUMBERS, false)
24 | ->setOptionValue(RequirementPasswordGenerator::OPTION_SYMBOLS, false)
25 | ->setOptionValue(RequirementPasswordGenerator::OPTION_AVOID_SIMILAR, false);
26 | }
27 |
28 | /**
29 | * @dataProvider lengthProvider
30 | *
31 | * @param $length
32 | */
33 | public function testLength($length): void
34 | {
35 | $this->_object->setLength($length);
36 | $this->assertSame($this->_object->getLength(), $length);
37 | }
38 |
39 | /**
40 | * @dataProvider lengthProvider
41 | *
42 | * @param $length
43 | */
44 | public function testGeneratePassword($length): void
45 | {
46 | $this->_object
47 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
48 | ->setOptionValue(RequirementPasswordGenerator::OPTION_LOWER_CASE, true)
49 | ->setOptionValue(RequirementPasswordGenerator::OPTION_NUMBERS, true)
50 | ->setOptionValue(RequirementPasswordGenerator::OPTION_SYMBOLS, true)
51 | ->setOptionValue(RequirementPasswordGenerator::OPTION_AVOID_SIMILAR, true);
52 |
53 | $this->_object->setLength($length);
54 | $this->assertSame(\mb_strlen($this->_object->generatePassword()), $length);
55 | }
56 |
57 | /**
58 | * @return array
59 | */
60 | public function lengthProvider()
61 | {
62 | return array(
63 | array(1),
64 | array(4),
65 | array(8),
66 | array(16),
67 | );
68 | }
69 |
70 |
71 | /**
72 | * @dataProvider lengthProvider
73 | *
74 | * @param $length
75 | */
76 | public function testGenerateMultiBytePassword($length): void
77 | {
78 | $this->_object
79 | ->setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, true)
80 | ->setOptionValue(ComputerPasswordGenerator::OPTION_LOWER_CASE, true)
81 | ->setParameter(ComputerPasswordGenerator::PARAMETER_UPPER_CASE, 'ßAÄÖÜÉÑÇŠŽДЖЮИЫ')
82 | ->setParameter(ComputerPasswordGenerator::PARAMETER_LOWER_CASE, 'ßaäöüéñçšžджюиы')
83 | ;
84 |
85 | $this->_object->setLength($length);
86 | $generatedPassword = $this->_object->generatePassword();
87 |
88 | $this->assertSame(\mb_strlen($generatedPassword), $length);
89 |
90 | $uppercase = $this->_object->getParameter(ComputerPasswordGenerator::PARAMETER_UPPER_CASE);
91 | $lowercase = $this->_object->getParameter(ComputerPasswordGenerator::PARAMETER_LOWER_CASE);
92 |
93 | // Check each character in the generated password
94 | foreach (mb_str_split($generatedPassword) as $char) {
95 | $this->assertTrue(mb_strpos($uppercase, $char) !== false || mb_strpos($lowercase, $char) !== false, "Character '{$char}' is not in the allowed character sets");
96 | }
97 |
98 | $this->_object->validatePassword($generatedPassword);
99 | }
100 |
101 | public function testGeneratePasswordNonIntException(): void
102 | {
103 | $this->expectException('\InvalidArgumentException');
104 | $this->_object->generatePasswords('A');
105 | }
106 |
107 | public function testGeneratePasswordNegativeIntException(): void
108 | {
109 | $this->expectException('\InvalidArgumentException');
110 | $this->_object->generatePasswords(-1);
111 | }
112 |
113 | /**
114 | * @dataProvider getterSetterProvider
115 | *
116 | * @param $method
117 | */
118 | public function testGetterSetters($method): void
119 | {
120 | $this->_object->{'set'.$method}(true);
121 | $this->assertTrue($this->_object->{'get'.$method}());
122 |
123 |
124 | $this->_object->{'set'.$method}(false);
125 | $this->assertTrue(!$this->_object->{'get'.$method}());
126 | }
127 |
128 | /**
129 | * @dataProvider lengthExceptionProvider
130 | *
131 | * @param $param
132 | */
133 | public function testLengthException($param): void
134 | {
135 | $this->expectException(\InvalidArgumentException::class);
136 | $this->_object->setLength($param);
137 | }
138 |
139 | public function lengthExceptionProvider()
140 | {
141 | return array(
142 | array('a'),
143 | array(false),
144 | array(null),
145 | array(-1),
146 | );
147 | }
148 |
149 | /**
150 | * @dataProvider getterSetterProvider
151 | *
152 | * @param $method
153 | */
154 | public function testGetterSettersException($method): void
155 | {
156 | $this->expectException(\InvalidArgumentException::class);
157 | $this->_object->{'set'.$method}(1);
158 | }
159 |
160 | public function getterSetterProvider()
161 | {
162 | return array(
163 | array('Uppercase'),
164 | array('Lowercase'),
165 | array('Numbers'),
166 | array('Symbols'),
167 | array('AvoidSimilar'),
168 | );
169 | }
170 |
171 | /**
172 | * @dataProvider optionProvider
173 | *
174 | * @param $option
175 | * @param $exists
176 | * @param $dontExist
177 | */
178 | public function testSetOption($option, $exists, $dontExist): void
179 | {
180 | $this->_object->setOptionValue($option, true);
181 | $availableCharacters = $this->_object->getCharacterList()->getCharacters();
182 |
183 | foreach ($exists as $check) {
184 | $this->assertStringContainsString($check, $availableCharacters);
185 | }
186 | foreach ($dontExist as $check) {
187 | $this->assertStringNotContainsString($check, $availableCharacters);
188 | }
189 | }
190 |
191 | /**
192 | * @return array
193 | */
194 | public function optionProvider()
195 | {
196 | return array(
197 | array(RequirementPasswordGenerator::OPTION_UPPER_CASE, array('A', 'B', 'C'), array('a', 'b', 'c')),
198 | array(RequirementPasswordGenerator::OPTION_LOWER_CASE, array('a', 'b', 'c'), array('A', 'B', 'C')),
199 | array(RequirementPasswordGenerator::OPTION_NUMBERS, array('1', '2', '3'), array('a', 'b', 'c', 'A', 'B', 'C')),
200 | array(RequirementPasswordGenerator::OPTION_SYMBOLS, array('+', '=', '?'), array('a', 'b', 'c', 'A', 'B', 'C')),
201 | );
202 | }
203 |
204 | public function testSetOptionSimilar(): void
205 | {
206 | $exists = array('a', 'b', 'c', 'A', 'B', 'C');
207 | $dontExist = array('o', 'l', 'O');
208 |
209 | $this->_object
210 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
211 | ->setOptionValue(RequirementPasswordGenerator::OPTION_LOWER_CASE, true)
212 | ->setOptionValue(RequirementPasswordGenerator::OPTION_AVOID_SIMILAR, true);
213 |
214 | $availableCharacters = $this->_object->getCharacterList()->getCharacters();
215 |
216 | foreach ($exists as $check) {
217 | $this->assertStringContainsString($check, $availableCharacters);
218 | }
219 | foreach ($dontExist as $check) {
220 | $this->assertStringNotContainsString($check, $availableCharacters);
221 | }
222 | }
223 |
224 | /**
225 | * @dataProvider optionsProvider
226 | *
227 | * @param $option
228 | * @param $parameter
229 | */
230 | public function testSetGet($option, $parameter): void
231 | {
232 | $this->_object
233 | ->setOptionValue($option, true)
234 | ->setParameter($parameter, 'A')
235 | ->setLength(4);
236 |
237 | $this->assertSame('AAAA', $this->_object->generatePassword());
238 | }
239 |
240 | /**
241 | * @return array
242 | */
243 | public function optionsProvider()
244 | {
245 | return array(
246 | array(RequirementPasswordGenerator::OPTION_UPPER_CASE, RequirementPasswordGenerator::PARAMETER_UPPER_CASE),
247 | array(RequirementPasswordGenerator::OPTION_LOWER_CASE, RequirementPasswordGenerator::PARAMETER_LOWER_CASE),
248 | array(RequirementPasswordGenerator::OPTION_NUMBERS, RequirementPasswordGenerator::PARAMETER_NUMBERS),
249 | array(RequirementPasswordGenerator::OPTION_SYMBOLS, RequirementPasswordGenerator::PARAMETER_SYMBOLS),
250 | );
251 | }
252 |
253 | /**
254 | *
255 | */
256 | public function testAvoidSimilar(): void
257 | {
258 | $this->_object
259 | ->setParameter(RequirementPasswordGenerator::PARAMETER_UPPER_CASE, 'AB')
260 | ->setParameter(RequirementPasswordGenerator::PARAMETER_SIMILAR, 'B')
261 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
262 | ->setOptionValue(RequirementPasswordGenerator::OPTION_AVOID_SIMILAR, true);
263 |
264 | $this->_object->setLength(4);
265 |
266 | $this->assertSame('AAAA', $this->_object->generatePassword());
267 | }
268 |
269 | /**
270 | *
271 | */
272 | public function testCharacterListException(): void
273 | {
274 | $this->expectException('\Hackzilla\PasswordGenerator\Exception\CharactersNotFoundException');
275 | $this->_object->getCharacterList();
276 | }
277 |
278 | /**
279 | * @dataProvider validOptionProvider
280 | */
281 | public function testValidOption($option, $valid): void
282 | {
283 | $this->assertSame($valid, $this->_object->validOption($option));
284 | }
285 |
286 | public function validOptionProvider()
287 | {
288 | return array(
289 | array(RequirementPasswordGenerator::OPTION_UPPER_CASE, true),
290 | array(RequirementPasswordGenerator::OPTION_LOWER_CASE, true),
291 | array(RequirementPasswordGenerator::OPTION_NUMBERS, true),
292 | array(RequirementPasswordGenerator::OPTION_SYMBOLS, true),
293 | array(null, false),
294 | array('', false),
295 | array(RequirementPasswordGenerator::OPTION_AVOID_SIMILAR, false),
296 | array(RequirementPasswordGenerator::OPTION_LENGTH, false),
297 | );
298 | }
299 |
300 | /**
301 | * @dataProvider minMaxProvider
302 | *
303 | * @param $option
304 | * @param $count
305 | */
306 | public function testMinMax($option, $count): void
307 | {
308 | $this->_object->setMinimumCount($option, $count);
309 | $this->assertSame($count, $this->_object->getMinimumCount($option));
310 |
311 | $this->_object->setMaximumCount($option, $count);
312 | $this->assertSame($count, $this->_object->getMaximumCount($option));
313 | }
314 |
315 | public function minMaxProvider()
316 | {
317 | return array(
318 | array(RequirementPasswordGenerator::OPTION_UPPER_CASE, null),
319 | array(RequirementPasswordGenerator::OPTION_UPPER_CASE, 1),
320 | array(RequirementPasswordGenerator::OPTION_UPPER_CASE, 2),
321 | array(RequirementPasswordGenerator::OPTION_LOWER_CASE, null),
322 | array(RequirementPasswordGenerator::OPTION_LOWER_CASE, 1),
323 | array(RequirementPasswordGenerator::OPTION_LOWER_CASE, 2),
324 | array(RequirementPasswordGenerator::OPTION_NUMBERS, null),
325 | array(RequirementPasswordGenerator::OPTION_NUMBERS, 1),
326 | array(RequirementPasswordGenerator::OPTION_NUMBERS, 2),
327 | array(RequirementPasswordGenerator::OPTION_SYMBOLS, null),
328 | array(RequirementPasswordGenerator::OPTION_SYMBOLS, 1),
329 | array(RequirementPasswordGenerator::OPTION_SYMBOLS, 2),
330 | );
331 | }
332 |
333 | public function testSetMinimumCountException(): void
334 | {
335 | $this->expectException('\InvalidArgumentException');
336 | $this->_object->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 'A');
337 | }
338 |
339 | public function testSetMaximumCountException(): void
340 | {
341 | $this->expectException('\InvalidArgumentException');
342 | $this->_object->setMaximumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 'A');
343 | }
344 |
345 | public function testValidLimits(): void
346 | {
347 | $this->_object
348 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
349 | ->setOptionValue(RequirementPasswordGenerator::OPTION_LOWER_CASE, true)
350 | ->setOptionValue(RequirementPasswordGenerator::OPTION_NUMBERS, true)
351 | ->setOptionValue(RequirementPasswordGenerator::OPTION_SYMBOLS, true)
352 | ->setLength(4)
353 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 1)
354 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_LOWER_CASE, 1)
355 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_NUMBERS, 1)
356 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_SYMBOLS, 1)
357 | ;
358 |
359 | $this->assertTrue($this->_object->validLimits());
360 | }
361 |
362 | public function testValidLimitsFalse(): void
363 | {
364 | $this->_object
365 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
366 | ->setOptionValue(RequirementPasswordGenerator::OPTION_LOWER_CASE, true)
367 | ->setOptionValue(RequirementPasswordGenerator::OPTION_NUMBERS, true)
368 | ->setOptionValue(RequirementPasswordGenerator::OPTION_SYMBOLS, true)
369 | ->setLength(3)
370 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 1)
371 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_LOWER_CASE, 1)
372 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_NUMBERS, 1)
373 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_SYMBOLS, 1)
374 | ;
375 |
376 | $this->assertFalse($this->_object->validLimits());
377 | }
378 |
379 | public function testvalidLimitsFalse2(): void
380 | {
381 | $this->_object
382 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
383 | ->setOptionValue(RequirementPasswordGenerator::OPTION_LOWER_CASE, true)
384 | ->setOptionValue(RequirementPasswordGenerator::OPTION_NUMBERS, true)
385 | ->setOptionValue(RequirementPasswordGenerator::OPTION_SYMBOLS, true)
386 | ->setLength(3)
387 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 4)
388 | ;
389 |
390 | $this->assertFalse($this->_object->validLimits());
391 | }
392 |
393 | public function testValidLimitsMaxFalse(): void
394 | {
395 | $this->_object
396 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
397 | ->setOptionValue(RequirementPasswordGenerator::OPTION_LOWER_CASE, true)
398 | ->setOptionValue(RequirementPasswordGenerator::OPTION_NUMBERS, true)
399 | ->setOptionValue(RequirementPasswordGenerator::OPTION_SYMBOLS, true)
400 | ->setLength(5)
401 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 1)
402 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_LOWER_CASE, 1)
403 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_NUMBERS, 1)
404 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_SYMBOLS, 1)
405 | ;
406 |
407 | $this->assertFalse($this->_object->validLimits());
408 | }
409 |
410 | public function testGeneratePasswordException(): void
411 | {
412 | $this->_object
413 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
414 | ->setLength(4)
415 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 5)
416 | ;
417 |
418 | $this->expectException('\Hackzilla\PasswordGenerator\Exception\ImpossibleMinMaxLimitsException');
419 | $this->_object->generatePassword();
420 | }
421 |
422 | public function testMaxPartialValidLimits(): void
423 | {
424 | $this->_object
425 | ->setLength(4)
426 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
427 | ->setMaximumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 1)
428 | ;
429 |
430 | $this->assertFalse($this->_object->validLimits());
431 | }
432 |
433 | public function testMinPartialValidLimits(): void
434 | {
435 | $this->_object
436 | ->setLength(4)
437 | ->setOptionValue(RequirementPasswordGenerator::OPTION_UPPER_CASE, true)
438 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 5)
439 | ;
440 |
441 | $this->assertFalse($this->_object->validLimits());
442 | }
443 |
444 | /**
445 | * @dataProvider validatePasswordProvider
446 | *
447 | * @param $password
448 | * @param $option
449 | * @param $min
450 | * @param $max
451 | * @param $valid
452 | */
453 | public function testValidatePassword($password, $option, $min, $max, $valid): void
454 | {
455 | $this->_object->setMinimumCount($option, $min);
456 | $this->_object->setMaximumCount($option, $max);
457 |
458 | $this->assertSame($valid, $this->_object->validatePassword($password));
459 | }
460 |
461 | public function validatePasswordProvider()
462 | {
463 | return array(
464 | array('ABCDef', RequirementPasswordGenerator::OPTION_UPPER_CASE, 2, 3, false),
465 | array('ABCdef', RequirementPasswordGenerator::OPTION_UPPER_CASE, 2, 3, true),
466 | array('ABcdef', RequirementPasswordGenerator::OPTION_UPPER_CASE, 2, 3, true),
467 | array('Abcdef', RequirementPasswordGenerator::OPTION_UPPER_CASE, 2, 3, false),
468 | array('ABCdef^\'%', RequirementPasswordGenerator::OPTION_SYMBOLS, 2, 3, true),
469 | array('ABcdef!@', RequirementPasswordGenerator::OPTION_SYMBOLS, 2, 3, true),
470 | array('Abcdef!', RequirementPasswordGenerator::OPTION_SYMBOLS, 2, 3, false),
471 | );
472 | }
473 |
474 | /**
475 | * @dataProvider minLengthProvider
476 | *
477 | * @param $length
478 | */
479 | public function testMinGeneratePassword($length): void
480 | {
481 | $this->_object
482 | ->setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, true)
483 | ->setOptionValue(ComputerPasswordGenerator::OPTION_LOWER_CASE, true)
484 | ->setOptionValue(ComputerPasswordGenerator::OPTION_NUMBERS, true)
485 | ->setOptionValue(ComputerPasswordGenerator::OPTION_SYMBOLS, true)
486 | ->setOptionValue(ComputerPasswordGenerator::OPTION_AVOID_SIMILAR, true)
487 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_UPPER_CASE, 2)
488 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_LOWER_CASE, 2)
489 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_NUMBERS, 2)
490 | ->setMinimumCount(RequirementPasswordGenerator::OPTION_SYMBOLS, 2)
491 | ;
492 |
493 | $this->_object->setLength($length);
494 |
495 | $this->assertTrue($this->_object->validLimits());
496 |
497 | $passwords = $this->_object->generatePasswords(5);
498 | $this->assertCount(5, $passwords);
499 |
500 | foreach ($passwords as $password) {
501 | $this->assertSame($length, \mb_strlen($password));
502 | }
503 | }
504 |
505 | /**
506 | * @return array
507 | */
508 | public function minLengthProvider()
509 | {
510 | return array(
511 | array(8),
512 | array(16),
513 | );
514 | }
515 |
516 | /**
517 | * @dataProvider countOptionExceptionProvider
518 | * @expectException \Hackzilla\PasswordGenerator\Exception\InvalidOptionException
519 | *
520 | * @param $method
521 | * @param $option
522 | */
523 | public function testCountOptionException($method, $option): void
524 | {
525 | $this->expectException(InvalidOptionException::class);
526 | $this->_object->{$method}($option, 1);
527 | }
528 |
529 | public function countOptionExceptionProvider()
530 | {
531 | return array(
532 | array('setMinimumCount', 'INVALID_OPTION'),
533 | array('setMaximumCount', 'INVALID_OPTION'),
534 | );
535 | }
536 |
537 | /**
538 | * @dataProvider countValueExceptionProvider
539 | *
540 | * @param $method
541 | * @param $option
542 | */
543 | public function testCountValueException($method, $option): void
544 | {
545 | $this->expectException(\InvalidArgumentException::class);
546 | $this->_object->{$method}($option, 0);
547 | }
548 |
549 | public function countValueExceptionProvider()
550 | {
551 | return array(
552 | array('setMinimumCount', 'INVALID_OPTION'),
553 | array('setMaximumCount', 'INVALID_OPTION'),
554 | );
555 | }
556 | }
557 |
--------------------------------------------------------------------------------
/Tests/Model/CharacterSetTest.php:
--------------------------------------------------------------------------------
1 | assertSame($result, $characterSet->getCharacters());
20 | }
21 |
22 | public function characterProvider()
23 | {
24 | return array(
25 | array('ABC', 'ABC'),
26 | array('', ''),
27 | );
28 | }
29 |
30 | /**
31 | * @dataProvider castCharacterProvider
32 | *
33 | * @param $characters
34 | * @param $result
35 | */
36 | public function testConstructCast($characters, $result): void
37 | {
38 | $characterSet = new CharacterSet($characters);
39 |
40 | $this->assertSame($result, $characterSet->__toString());
41 | $this->assertSame($result, (string) $characterSet);
42 | }
43 |
44 | public function castCharacterProvider()
45 | {
46 | return array(
47 | array('ABC', 'ABC'),
48 | array('', ''),
49 | );
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/Tests/Model/Option/BooleanOptionTest.php:
--------------------------------------------------------------------------------
1 | assertInstanceOf('Hackzilla\PasswordGenerator\Model\Option\OptionInterface', $option);
14 | $this->assertInstanceOf('Hackzilla\PasswordGenerator\Model\Option\BooleanOption', $option);
15 | }
16 |
17 | public function testType()
18 | {
19 | $option = new BooleanOption();
20 |
21 | $this->assertSame(BooleanOption::TYPE_BOOLEAN, $option->getType());
22 | }
23 |
24 | /**
25 | * @dataProvider validValueProvider
26 | *
27 | * @param mixed $value
28 | */
29 | public function testValidValue($value)
30 | {
31 | $option = new BooleanOption();
32 | $option->setValue($value);
33 |
34 | $this->assertSame($option->getValue(), $value);
35 | }
36 |
37 | public function validValueProvider()
38 | {
39 | return array(
40 | array(true),
41 | array(false),
42 | );
43 | }
44 |
45 | /**
46 | * @dataProvider invalidValueProvider
47 | *
48 | * @param mixed $value
49 | */
50 | public function testInvalidValue($value)
51 | {
52 | $this->expectException(\InvalidArgumentException::class);
53 |
54 | $option = new BooleanOption();
55 | $option->setValue($value);
56 | }
57 |
58 | public function invalidValueProvider()
59 | {
60 | return array(
61 | array(1),
62 | array(null),
63 | array(1.1),
64 | array('a'),
65 | );
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/Tests/Model/Option/IntegerOptionTest.php:
--------------------------------------------------------------------------------
1 | assertInstanceOf('Hackzilla\PasswordGenerator\Model\Option\OptionInterface', $option);
14 | $this->assertInstanceOf('Hackzilla\PasswordGenerator\Model\Option\IntegerOption', $option);
15 | }
16 |
17 | public function testType()
18 | {
19 | $option = new IntegerOption();
20 |
21 | $this->assertSame(IntegerOption::TYPE_INTEGER, $option->getType());
22 | }
23 |
24 | /**
25 | * @dataProvider validValueProvider
26 | *
27 | * @param mixed $value
28 | */
29 | public function testValidValue($value)
30 | {
31 | $option = new IntegerOption();
32 | $option->setValue($value);
33 |
34 | $this->assertSame($option->getValue(), $value);
35 | }
36 |
37 | public function validValueProvider()
38 | {
39 | return array(
40 | array(1),
41 | );
42 | }
43 |
44 | /**
45 | * @dataProvider invalidValueProvider
46 | *
47 | * @param mixed $value
48 | */
49 | public function testInvalidValue($value)
50 | {
51 | $this->expectException(\InvalidArgumentException::class);
52 |
53 | $option = new IntegerOption();
54 | $option->setValue($value);
55 | }
56 |
57 | public function invalidValueProvider()
58 | {
59 | return array(
60 | array(true),
61 | array(false),
62 | array(null),
63 | array(1.1),
64 | array('a'),
65 | );
66 | }
67 |
68 | /**
69 | * @dataProvider minMaxProvider
70 | *
71 | * @param $min
72 | * @param $max
73 | * @param $value
74 | */
75 | public function testMinMax($min, $max, $value)
76 | {
77 | $option = new IntegerOption(array('min' => $min, 'max' => $max));
78 | $option->setValue($value);
79 |
80 | $this->assertSame($option->getValue(), $value);
81 | }
82 |
83 | public function minMaxProvider()
84 | {
85 | return array(
86 | array(0, 255, 10),
87 | array(10, 10, 10),
88 | array(10, 15, 10),
89 | array(-100, 0, -10),
90 | array(-100, -10, -50),
91 | );
92 | }
93 |
94 | /**
95 | * @dataProvider minMaxExceptionProvider
96 | *
97 | * @param $min
98 | * @param $max
99 | * @param $value
100 | */
101 | public function testMinMaxException($min, $max, $value)
102 | {
103 | $this->expectException(\InvalidArgumentException::class);
104 |
105 | $option = new IntegerOption(array('min' => $min, 'max' => $max));
106 | $option->setValue($value);
107 | }
108 |
109 | public function minMaxExceptionProvider()
110 | {
111 | return array(
112 | array(0, 255, 256),
113 | array(10, 10, 11),
114 | array(10, 15, -12),
115 | array(-100, 0, -101),
116 | array(-100, -10, -9),
117 | );
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/Tests/Model/Option/OptionClass.php:
--------------------------------------------------------------------------------
1 | assertInstanceOf('Hackzilla\PasswordGenerator\Model\Option\OptionInterface', $option);
20 | $this->assertInstanceOf($namespace, $option);
21 | $this->assertSame($type, $option->getType());
22 | }
23 |
24 | public function testCreateFromTypeNull()
25 | {
26 | $this->assertNull(Option::createFromType('fail'));
27 | }
28 |
29 | public function typeProvider()
30 | {
31 | return array(
32 | array(Option::TYPE_BOOLEAN, 'Hackzilla\PasswordGenerator\Model\Option\BooleanOption'),
33 | array(Option::TYPE_INTEGER, 'Hackzilla\PasswordGenerator\Model\Option\IntegerOption'),
34 | array(Option::TYPE_STRING, 'Hackzilla\PasswordGenerator\Model\Option\StringOption'),
35 | );
36 | }
37 |
38 | public function testDefault()
39 | {
40 | $option = new OptionClass();
41 | $this->assertSame($option->getValue(), null);
42 |
43 | $option = new OptionClass(array('default' => 1));
44 | $this->assertSame($option->getValue(), 1);
45 |
46 | $option = new OptionClass(array('default' => 'a'));
47 | $this->assertSame($option->getValue(), 'a');
48 | }
49 |
50 | /**
51 | * @dataProvider valueProvider
52 | *
53 | * @param mixed $value
54 | */
55 | public function testValue($value)
56 | {
57 | $option = new OptionClass();
58 | $option->setValue($value);
59 |
60 | $this->assertSame($option->getValue(), $value);
61 | }
62 |
63 | public function valueProvider()
64 | {
65 | return array(
66 | array(true),
67 | array(1),
68 | array(null),
69 | array(1.1),
70 | array('a'),
71 | );
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Tests/Model/Option/StringOptionTest.php:
--------------------------------------------------------------------------------
1 | assertInstanceOf('Hackzilla\PasswordGenerator\Model\Option\OptionInterface', $option);
14 | $this->assertInstanceOf('Hackzilla\PasswordGenerator\Model\Option\StringOption', $option);
15 | }
16 |
17 | public function testType()
18 | {
19 | $option = new StringOption();
20 |
21 | $this->assertSame(StringOption::TYPE_STRING, $option->getType());
22 | }
23 |
24 | /**
25 | * @dataProvider validValueProvider
26 | *
27 | * @param mixed $value
28 | */
29 | public function testValidValue($value)
30 | {
31 | $option = new StringOption();
32 | $option->setValue($value);
33 |
34 | $this->assertSame($option->getValue(), $value);
35 | }
36 |
37 | public function validValueProvider()
38 | {
39 | return array(
40 | array('a'),
41 | );
42 | }
43 |
44 | /**
45 | * @dataProvider invalidValueProvider
46 | *
47 | * @param mixed $value
48 | */
49 | public function testInvalidValue($value)
50 | {
51 | $this->expectException(\InvalidArgumentException::class);
52 |
53 | $option = new StringOption();
54 | $option->setValue($value);
55 | }
56 |
57 | public function invalidValueProvider()
58 | {
59 | return array(
60 | array(true),
61 | array(false),
62 | array(1),
63 | array(null),
64 | array(1.1),
65 | );
66 | }
67 |
68 | /**
69 | * @dataProvider minMaxExceptionProvider
70 | *
71 | * @param $min
72 | * @param $max
73 | * @param $value
74 | */
75 | public function testMinMaxException($min, $max, $value)
76 | {
77 | $this->expectException(\InvalidArgumentException::class);
78 |
79 | $option = new StringOption(array('min' => $min, 'max' => $max));
80 | $option->setValue($value);
81 | }
82 |
83 | public function minMaxExceptionProvider()
84 | {
85 | return array(
86 | array(0, 5, 'abcdef'),
87 | array(0, 1, 'ab'),
88 | array(1, 15, ''),
89 | );
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/Tests/RandomGenerator/NoRandomGeneratorTest.php:
--------------------------------------------------------------------------------
1 | _object = new NoRandomGenerator();
14 | }
15 |
16 | public function rangeProvider()
17 | {
18 | return array(
19 | array(1, 100),
20 | array(10, 20),
21 | array(0, 5),
22 | array(1, 2),
23 | );
24 | }
25 |
26 | /**
27 | * @dataProvider rangeProvider
28 | *
29 | * @param int $min
30 | * @param int $max
31 | */
32 | public function testRandomGenerator($min, $max)
33 | {
34 | $randomInteger = $this->_object->randomInteger($min, $max);
35 |
36 | $this->assertSame($min, $randomInteger);
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/Tests/RandomGenerator/Php5RandomGeneratorTest.php:
--------------------------------------------------------------------------------
1 | _object = new Php5RandomGenerator();
14 | }
15 |
16 | public function rangeProvider()
17 | {
18 | return array(
19 | array(1, 100),
20 | array(10, 20),
21 | array(0, 5),
22 | array(1, 2),
23 | );
24 | }
25 |
26 | /**
27 | * @dataProvider rangeProvider
28 | *
29 | * @param int $min
30 | * @param int $max
31 | */
32 | public function testRandomGenerator($min, $max): void
33 | {
34 | $randomInteger = $this->_object->randomInteger($min, $max);
35 |
36 | $this->assertGreaterThanOrEqual($min, $randomInteger);
37 | $this->assertLessThanOrEqual($max, $randomInteger);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/Tests/RandomGenerator/Php7RandomGeneratorTest.php:
--------------------------------------------------------------------------------
1 | _object = new Php7RandomGenerator();
19 | }
20 |
21 | public function rangeProvider()
22 | {
23 | return array(
24 | array(1, 100),
25 | array(10, 20),
26 | array(0, 5),
27 | array(1, 2),
28 | );
29 | }
30 |
31 | /**
32 | * @dataProvider rangeProvider
33 | *
34 | * @param int $min
35 | * @param int $max
36 | */
37 | public function testRandomGenerator($min, $max): void
38 | {
39 | $randomInteger = $this->_object->randomInteger($min, $max);
40 |
41 | $this->assertGreaterThanOrEqual($min, $randomInteger);
42 | $this->assertLessThanOrEqual($max, $randomInteger);
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/Tests/ReadMeTest.php:
--------------------------------------------------------------------------------
1 | setOptionValue(ComputerPasswordGenerator::OPTION_UPPER_CASE, true)
19 | ->setOptionValue(ComputerPasswordGenerator::OPTION_LOWER_CASE, true)
20 | ->setOptionValue(ComputerPasswordGenerator::OPTION_NUMBERS, true)
21 | ->setOptionValue(ComputerPasswordGenerator::OPTION_SYMBOLS, false)
22 | ;
23 |
24 | $this->assertIsString($generator->generatePassword());
25 | }
26 |
27 | public function testMorePasswordsUsage()
28 | {
29 | $generator = new ComputerPasswordGenerator();
30 |
31 | $generator
32 | ->setUppercase()
33 | ->setLowercase()
34 | ->setNumbers()
35 | ->setSymbols(false)
36 | ->setLength(12);
37 |
38 | $passwords = $generator->generatePasswords(10);
39 |
40 | $this->assertCount(10, $passwords);
41 | $this->assertIsString($passwords[0]);
42 | }
43 |
44 | public function testHybridPasswordGeneratorUsage()
45 | {
46 | $generator = new HybridPasswordGenerator();
47 |
48 | $generator
49 | ->setUppercase()
50 | ->setLowercase()
51 | ->setNumbers()
52 | ->setSymbols(false)
53 | ->setSegmentLength(3)
54 | ->setSegmentCount(4)
55 | ->setSegmentSeparator('-');
56 |
57 | $passwords = $generator->generatePasswords(10);
58 |
59 | $this->assertCount(10, $passwords);
60 | $this->assertIsString($passwords[0]);
61 | }
62 |
63 | public function testHumanPasswordGeneratorUsage()
64 | {
65 | $generator = new HumanPasswordGenerator();
66 |
67 | $generator
68 | ->setWordList('/usr/share/dict/words')
69 | ->setMinWordLength(5)
70 | ->setMaxWordLength(8)
71 | ->setWordCount(3)
72 | ->setWordSeparator('-');
73 |
74 | $passwords = $generator->generatePasswords(10);
75 |
76 | $this->assertCount(10, $passwords);
77 | $this->assertIsString($passwords[0]);
78 | }
79 |
80 | /**
81 | * @throws \Hackzilla\PasswordGenerator\Exception\FileNotFoundException
82 | */
83 | public function testPhp5RandomGeneratorUsage()
84 | {
85 | $generator = new HumanPasswordGenerator();
86 |
87 | $generator
88 | ->setRandomGenerator(new Php5RandomGenerator())
89 | ->setWordList('/usr/share/dict/words')
90 | ->setMinWordLength(5)
91 | ->setMaxWordLength(8)
92 | ->setWordCount(3)
93 | ->setWordSeparator('-');
94 |
95 | $passwords = $generator->generatePasswords(10);
96 |
97 | $this->assertCount(10, $passwords);
98 | $this->assertIsString($passwords[0]);
99 | }
100 |
101 | /**
102 | * @requires PHP 7
103 | *
104 | * @throws \Hackzilla\PasswordGenerator\Exception\FileNotFoundException
105 | */
106 | public function testPhp7RandomGeneratorUsage()
107 | {
108 | $generator = new HumanPasswordGenerator();
109 |
110 | $generator
111 | ->setRandomGenerator(new Php7RandomGenerator())
112 | ->setWordList('/usr/share/dict/words')
113 | ->setMinWordLength(5)
114 | ->setMaxWordLength(8)
115 | ->setWordCount(3)
116 | ->setWordSeparator('-');
117 |
118 | $passwords = $generator->generatePasswords(10);
119 |
120 | $this->assertCount(10, $passwords);
121 | $this->assertIsString($passwords[0]);
122 | }
123 | }
124 |
--------------------------------------------------------------------------------
/Tests/bootstrap.php:
--------------------------------------------------------------------------------
1 | =8.0",
15 | "ext-mbstring": "*"
16 | },
17 | "require-dev": {
18 | "phpunit/phpunit": "^9.0"
19 | },
20 | "autoload": {
21 | "psr-4": {
22 | "Hackzilla\\PasswordGenerator\\": ""
23 | }
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | ./
6 |
7 |
8 |
9 | ./Resources
10 | ./Tests
11 | ./vendor
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | ./Tests
22 |
23 |
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/travis.phpunit.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
17 | ./Tests
18 |
19 |
20 |
21 |
22 |
23 | ./
24 |
25 | ./Resources
26 | ./Tests
27 | ./vendor
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------