Repository: dubzzz/fast-check
Pull request #2709 (2022-02-02 08:28:03)

🐛 Cap the max generated length with max length
<!-- Context of the PR: short description and potentially linked issues -->

<!-- ...a few words to describe the content of this PR...               -->
<!-- ... -->

<!-- Type of PR: [ ] unchecked / [ ] checked -->
**_Category:_**

- [ ] ✨ Introduce new features
- [ ] 📝 Add or update documentation
- [ ] ✅ Add or update tests
- [x] 🐛 Fix a bug
- [ ] 🏷️ Add or update types
- [ ] ⚡️ Improve performance
- [ ] _Other(s):_ ...
<!-- Don't forget to add the gitmoji icon in the name of the PR -->
<!-- See: https://gitmoji.dev/                                  -->

<!-- Fixing bugs, adding features... may impact existing ones           -->
<!-- in order to track potential issues that could be related to your PR -->
<!-- please check the impacts and describe more precisely what to expect -->

**_Potential impacts:_**

<!-- Generated values: Can your change impact any of the existing generators in terms of generated values, if so which ones? when? -->
<!-- Shrink values:    Can your change impact any of the existing generators in terms of shrink values, if so which ones? when? -->
<!-- Performance:      Can it require some typings changes on user side? Please give more details -->
<!-- Typings:          Is there a potential performance impact? In which cases? -->
- [ ] Generated values
- [ ] Shrink values
- [ ] Performance
- [ ] Typings
- [ ] _Other(s):_ ...


codesandbox[bot]: This pull request is automatically built and testable in [CodeSandbox](https://codesandbox.io).

  To see build info of the built libraries, click [here](https://ci.codesandbox.io/status/dubzzz/fast-check/pr/2709/builds/214443) or the icon next to each commit SHA.

Latest deployment of this branch, based on commit 6cbedf3d9b7e4bef8843ece1df7fdb8f782b4415:

|Sandbox| Source |
|--|--|
|[Vanilla](https://codesandbox.io/s/vanilla-1qddp)| Configuration |

codecov[bot]: # [Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/2709?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) Report
> Merging [#2709](https://codecov.io/gh/dubzzz/fast-check/pull/2709?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) (6cbedf3) into [main](https://codecov.io/gh/dubzzz/fast-check/commit/89689c4f53d0674676f4321b09cc41b2ae776a27?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) (89689c4) will **decrease** coverage by `0.02%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/dubzzz/fast-check/pull/2709/graphs/tree.svg?width=650&height=150&src=pr&token=fRi2fJN730&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN)](https://codecov.io/gh/dubzzz/fast-check/pull/2709?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN)

```diff
@@            Coverage Diff             @@
##             main    #2709      +/-   ##
==========================================
- Coverage   95.00%   94.98%   -0.03%     
==========================================
  Files         211      211              
  Lines        4906     4906              
  Branches      968      968              
==========================================
- Hits         4661     4660       -1     
- Misses        241      242       +1     
  Partials        4        4              
```

| Flag | Coverage Δ | |
|---|---|---|
| unit-tests | `94.98% <100.00%> (-0.03%)` | :arrow_down: |

Flags with carried forward coverage won't be shown. [Click here](https://docs.codecov.io/docs/carryforward-flags?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN#carryforward-flags-in-the-pull-request-comment) to find out more.

| [Impacted Files](https://codecov.io/gh/dubzzz/fast-check/pull/2709?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN) | Coverage Δ | |
|---|---|---|
| [...trary/\_internals/helpers/MaxLengthFromMinLength.ts](https://codecov.io/gh/dubzzz/fast-check/pull/2709/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN#diff-c3JjL2FyYml0cmFyeS9faW50ZXJuYWxzL2hlbHBlcnMvTWF4TGVuZ3RoRnJvbU1pbkxlbmd0aC50cw==) | `92.50% <100.00%> (ø)` | |
| [src/arbitrary/\_internals/mappers/ArrayToMap.ts](https://codecov.io/gh/dubzzz/fast-check/pull/2709/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN#diff-c3JjL2FyYml0cmFyeS9faW50ZXJuYWxzL21hcHBlcnMvQXJyYXlUb01hcC50cw==) | `87.50% <0.00%> (-12.50%)` | :arrow_down: |

------

[Continue to review full report at Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/2709?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/dubzzz/fast-check/pull/2709?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN). Last update [c2ae3a6...6cbedf3](https://codecov.io/gh/dubzzz/fast-check/pull/2709?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Nicolas+DUBIEN).


Patch:
diff --git a/src/arbitrary/_internals/helpers/MaxLengthFromMinLength.ts b/src/arbitrary/_internals/helpers/MaxLengthFromMinLength.ts
index a305b986..cc507421 100644
--- a/src/arbitrary/_internals/helpers/MaxLengthFromMinLength.ts
+++ b/src/arbitrary/_internals/helpers/MaxLengthFromMinLength.ts
@@ -56,15 +56,15 @@ export const DefaultSize: Size = 'small';
 export function maxLengthFromMinLength(minLength: number, size: Size): number {
   switch (size) {
     case 'xsmall':
-      return Math.min(Math.floor(1.1 * minLength) + 1, 0x7fffffff); // min + (0.1 * min + 1)
+      return Math.floor(1.1 * minLength) + 1; // min + (0.1 * min + 1)
     case 'small':
-      return Math.min(2 * minLength + 10, 0x7fffffff); // min + (1 * min + 10)
+      return 2 * minLength + 10; // min + (1 * min + 10)
     case 'medium':
-      return Math.min(11 * minLength + 100, 0x7fffffff); // min + (10 * min + 100)
+      return 11 * minLength + 100; // min + (10 * min + 100)
     case 'large':
-      return Math.min(101 * minLength + 1000, 0x7fffffff); // min + (100 * min + 1000)
+      return 101 * minLength + 1000; // min + (100 * min + 1000)
     case 'xlarge':
-      return Math.min(1001 * minLength + 10000, 0x7fffffff); // min + (1000 * min + 10000)
+      return 1001 * minLength + 10000; // min + (1000 * min + 10000)
     default:
       throw new Error(`Unable to compute lengths based on received size: ${size}`);
   }
@@ -119,5 +119,5 @@ export function maxGeneratedLengthFromSizeForArbitrary(
     return maxLength;
   }
   const finalSize = relativeSizeToSize(definedSize, defaultSize);
-  return maxLengthFromMinLength(minLength, finalSize);
+  return Math.min(maxLengthFromMinLength(minLength, finalSize), maxLength);
 }


Test patch:
diff --git a/test/unit/arbitrary/_internals/helpers/MaxLengthFromMinLength.spec.ts b/test/unit/arbitrary/_internals/helpers/MaxLengthFromMinLength.spec.ts
index 33932338..d89928d1 100644
--- a/test/unit/arbitrary/_internals/helpers/MaxLengthFromMinLength.spec.ts
+++ b/test/unit/arbitrary/_internals/helpers/MaxLengthFromMinLength.spec.ts
@@ -6,6 +6,7 @@ import {
   MaxLengthUpperBound,
   relativeSizeToSize,
 } from '../../../../../src/arbitrary/_internals/helpers/MaxLengthFromMinLength';
+import { configureGlobal, readConfigureGlobal } from '../../../../../src/check/runner/configuration/GlobalParameters';
 import { sizeArb, isSmallerSize, relativeSizeArb, sizeForArbitraryArb } from '../../__test-helpers__/SizeHelpers';
 
 describe('maxLengthFromMinLength', () => {
@@ -58,7 +59,7 @@ describe('maxGeneratedLengthFromSizeForArbitrary', () => {
 
           // Act
           const computedLength = maxGeneratedLengthFromSizeForArbitrary(size, minLength, maxLength, specifiedMaxLength);
-          const expectedLength = maxLengthFromMinLength(minLength, size);
+          const expectedLength = Math.min(maxLengthFromMinLength(minLength, size), maxLength);
 
           // Assert
           expect(computedLength).toBe(expectedLength);
@@ -176,6 +177,36 @@ describe('maxGeneratedLengthFromSizeForArbitrary', () => {
       )
     );
   });
+
+  it('should always return a length being between minLength and maxLength', () => {
+    fc.assert(
+      fc.property(
+        fc.record({ baseSize: sizeArb, defaultSizeToMaxWhenMaxSpecified: fc.boolean() }, { requiredKeys: [] }),
+        fc.option(sizeForArbitraryArb, { nil: undefined }),
+        fc.integer({ min: 0, max: MaxLengthUpperBound }),
+        fc.integer({ min: 0, max: MaxLengthUpperBound }),
+        fc.boolean(),
+        (config, size, lengthA, lengthB, specifiedMaxLength) => {
+          // Arrange
+          const [minLength, maxLength] = lengthA < lengthB ? [lengthA, lengthB] : [lengthB, lengthA];
+
+          // Act
+          let computedLength: number;
+          const previousConfiguration = readConfigureGlobal();
+          try {
+            configureGlobal(config);
+            computedLength = maxGeneratedLengthFromSizeForArbitrary(size, minLength, maxLength, specifiedMaxLength);
+          } finally {
+            configureGlobal(previousConfiguration || {});
+          }
+
+          // Assert
+          expect(computedLength).toBeGreaterThanOrEqual(minLength);
+          expect(computedLength).toBeLessThanOrEqual(maxLength);
+        }
+      )
+    );
+  });
 });
 
 describe('relativeSizeToSize', () => {