Page MenuHomePhabricator

D4731.id15263.diff
No OneTemporary

D4731.id15263.diff

diff --git a/web/utils/text-utils.js b/web/utils/text-utils.js
--- a/web/utils/text-utils.js
+++ b/web/utils/text-utils.js
@@ -1,4 +1,6 @@
// @flow
+import crypto from 'crypto';
+import invariant from 'invariant';
let canvas;
@@ -16,4 +18,34 @@
return Math.max(...widths);
}
-export { calculateMaxTextWidth };
+const numberOfPossibleByteValues = 256;
+
+function generateRandomString(length: number, availableSigns: string): string {
+ invariant(length >= 0, 'length must be non-negative');
+ invariant(
+ availableSigns !== '' || length === 0,
+ "cannot create a random string of non-zero length from availableSigns = ''",
+ );
+
+ const validByteUpperBound =
+ availableSigns.length *
+ Math.floor(numberOfPossibleByteValues / availableSigns.length);
+ const drawBytes =
+ length * (1 + 2 * (1 - validByteUpperBound / numberOfPossibleByteValues));
+
+ let str = '';
+
+ while (str.length < length) {
+ const rand = crypto.randomBytes(drawBytes);
+
+ for (let i = 0; str.length < length && i < drawBytes; i++) {
+ if (rand[i] < validByteUpperBound) {
+ const index = rand[i] % availableSigns.length;
+ str += availableSigns.charAt(index);
+ }
+ }
+ }
+ return str;
+}
+
+export { calculateMaxTextWidth, generateRandomString };
diff --git a/web/utils/text-utils.test.js b/web/utils/text-utils.test.js
new file mode 100644
--- /dev/null
+++ b/web/utils/text-utils.test.js
@@ -0,0 +1,42 @@
+// @flow
+
+import { generateRandomString } from './text-utils';
+
+describe('generateRandomString', () => {
+ it('should return an empty string when passed length = 0', () => {
+ expect(generateRandomString(0, 'abcde')).toMatch(/^$/);
+ expect(generateRandomString(0, '')).toMatch(/^$/);
+ });
+
+ it('should return a random string of length equal to length, containig only characters given in availableSigns', () => {
+ const length1 = 100;
+ const availableSigns1 = 'abcde';
+ expect(generateRandomString(length1, availableSigns1)).toMatch(
+ new RegExp('^[' + availableSigns1 + ']{' + length1.toString() + '}$'),
+ );
+
+ const length2 = 10;
+ const availableSigns2 = 'abcde0123456789!@#$%^&*';
+ expect(generateRandomString(length2, availableSigns2)).toMatch(
+ new RegExp('^[' + availableSigns2 + ']{' + length2.toString() + '}$'),
+ );
+
+ const length3 = 10;
+ const availableSigns3 = 'a';
+ expect(generateRandomString(length3, availableSigns3)).toMatch(
+ new RegExp('^[' + availableSigns3 + ']{' + length3.toString() + '}$'),
+ );
+ });
+
+ it('should throw an error when length is negative', () => {
+ expect(() => generateRandomString(-1, 'abc')).toThrow();
+ expect(() => generateRandomString(-1, '')).toThrow();
+ expect(() => generateRandomString(-123, 'abc')).toThrow();
+ expect(() => generateRandomString(-123, '')).toThrow();
+ });
+
+ it('should throw an error when availableSigns is an empty string, and length is positive', () => {
+ expect(() => generateRandomString(1, '')).toThrow();
+ expect(() => generateRandomString(10, '')).toThrow();
+ });
+});

File Metadata

Mime Type
text/plain
Expires
Wed, Nov 27, 11:41 PM (20 h, 54 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
2592106
Default Alt Text
D4731.id15263.diff (3 KB)

Event Timeline