github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/packages/pyroscope-flamegraph/src/format/format.spec.ts (about)

     1  import { numberWithCommas, getFormatter } from './format';
     2  
     3  describe('format', () => {
     4    describe.each([
     5      [0, '0'],
     6      [1_000, '1,000'],
     7      [1_000_000, '1,000,000'],
     8      [1_000_000_000, '1,000,000,000'],
     9      [-1_000, '-1,000'],
    10      [-1_000_000, '-1,000,000'],
    11      [-1_000_000_000, '-1,000,000,000'],
    12    ])('.numberWithCommas(%i)', (a: number, expected) => {
    13      it(`returns ${expected}`, () => {
    14        expect(numberWithCommas(a)).toBe(expected);
    15      });
    16    });
    17  
    18    describe('format & formatPrecise', () => {
    19      // TODO is this correct, since we have an enum?
    20      // unfortunately until we fully migrate to TS
    21      // we still need to check for a default value
    22      it('its constructor should default to DurationFormatter', () => {
    23        const df = getFormatter(80, 2, '' as any);
    24  
    25        expect(df.format(0.001, 100)).toBe('< 0.01  ');
    26        expect(df.formatPrecise(0.001, 100)).toBe('0.00001  ');
    27        expect(df.formatPrecise(0.1, 100)).toBe('0.001  ');
    28      });
    29  
    30      describe('DurationFormatter', () => {
    31        it('correctly formats duration when maxdur = 40', () => {
    32          const df = getFormatter(80, 2, 'samples');
    33  
    34          expect(df.format(0, 100)).toBe('0.00 seconds');
    35          expect(df.format(0.001, 100)).toBe('< 0.01 seconds');
    36          expect(df.format(100, 100)).toBe('1.00 second');
    37          expect(df.format(2000, 100)).toBe('20.00 seconds');
    38          expect(df.format(2012.3, 100)).toBe('20.12 seconds');
    39          expect(df.format(8000, 100)).toBe('80.00 seconds');
    40          expect(df.formatPrecise(0.001, 100)).toBe('0.00001 seconds');
    41        });
    42  
    43        it('correctly formats duration when maxdur = 80', () => {
    44          const df = getFormatter(160, 2, 'samples');
    45  
    46          expect(df.format(6000, 100)).toBe('1.00 minute');
    47          expect(df.format(100, 100)).toBe('0.02 minutes');
    48          expect(df.format(2000, 100)).toBe('0.33 minutes');
    49          expect(df.format(2012.3, 100)).toBe('0.34 minutes');
    50          expect(df.format(8000, 100)).toBe('1.33 minutes');
    51          expect(df.formatPrecise(1, 100)).toBe('0.00017 minutes');
    52        });
    53  
    54        it('correctly formats samples duration and return value without units', () => {
    55          const df = getFormatter(160, 2, 'samples');
    56  
    57          expect(df.suffix).toBe('minute');
    58          expect(df.format(6000, 100, false)).toBe('1.00');
    59          expect(df.format(100, 100, false)).toBe('0.02');
    60          expect(df.format(2000, 100, false)).toBe('0.33');
    61          expect(df.format(2012.3, 100, false)).toBe('0.34');
    62          expect(df.format(8000, 100, false)).toBe('1.33');
    63        });
    64  
    65        it('correctly formats trace samples', () => {
    66          const df = getFormatter(80, 2, 'trace_samples');
    67  
    68          expect(df.format(0.001, 100)).toBe('< 0.01 seconds');
    69          expect(df.format(100, 100)).toBe('1.00 second');
    70          expect(df.format(2000, 100)).toBe('20.00 seconds');
    71          expect(df.format(2012.3, 100)).toBe('20.12 seconds');
    72          expect(df.format(8000, 100)).toBe('80.00 seconds');
    73          expect(df.formatPrecise(0.001, 100)).toBe('0.00001 seconds');
    74        });
    75  
    76        it('correctly formats trace_samples duration when maxdur is less than second', () => {
    77          const df = getFormatter(10, 100, 'trace_samples');
    78  
    79          expect(df.format(55, 100)).toBe('550.00 ms');
    80          expect(df.format(100, 100)).toBe('1000.00 ms');
    81          expect(df.format(1.001, 100)).toBe('10.01 ms');
    82          expect(df.format(9999, 100)).toBe('99990.00 ms');
    83          expect(df.format(0.331, 100)).toBe('3.31 ms');
    84          expect(df.format(0.0001, 100)).toBe('< 0.01 ms');
    85          expect(df.formatPrecise(0.0001, 100)).toBe('0.001 ms');
    86        });
    87  
    88        it('correctly formats trace_samples duration when maxdur is less than ms', () => {
    89          const df = getFormatter(1, 10000, 'trace_samples');
    90  
    91          expect(df.format(0.012, 100)).toBe('120.00 μs');
    92          expect(df.format(0, 100)).toBe('0.00 μs');
    93          expect(df.format(0.0091, 100)).toBe('91.00 μs');
    94          expect(df.format(1.005199, 100)).toBe('10051.99 μs');
    95          expect(df.format(1.1, 100)).toBe('11000.00 μs');
    96          expect(df.format(0.000001, 100)).toBe('< 0.01 μs');
    97          expect(df.formatPrecise(0.0000001, 100)).toBe('0.001 μs');
    98        });
    99  
   100        it('correctly formats trace_samples duration when maxdur is hour', () => {
   101          const hour = 3600;
   102          let df = getFormatter(hour, 1, 'trace_samples');
   103  
   104          expect(df.format(0, 100)).toBe('0.00 hours');
   105          expect(df.format(hour * 100, 100)).toBe('1.00 hour');
   106          expect(df.format(0.6 * hour * 100, 100)).toBe('0.60 hours');
   107          expect(df.format(0.02 * hour * 100, 100)).toBe('0.02 hours');
   108          expect(df.format(0.001 * hour * 100, 100)).toBe('< 0.01 hours');
   109          expect(df.format(42.1 * hour * 100, 100)).toBe('42.10 hours');
   110          expect(df.formatPrecise(0.001 * hour * 100, 100)).toBe('0.001 hours');
   111        });
   112  
   113        it('correctly formats trace_samples duration when maxdur is day', () => {
   114          const day = 24 * 60 * 60;
   115          const df = getFormatter(day, 1, 'trace_samples');
   116  
   117          expect(df.format(day * 100, 100)).toBe('1.00 day');
   118          expect(df.format(12 * day * 100, 100)).toBe('12.00 days');
   119          expect(df.format(2.29 * day * 100, 100)).toBe('2.29 days');
   120          expect(df.format(0.11 * day * 100, 100)).toBe('0.11 days');
   121          expect(df.format(0.001 * day * 100, 100)).toBe('< 0.01 days');
   122          expect(df.formatPrecise(0.001 * day * 100, 100)).toBe('0.001 days');
   123        });
   124  
   125        it('correctly formats trace_samples duration when maxdur = month', () => {
   126          const month = 30 * 24 * 60 * 60;
   127          const df = getFormatter(month, 1, 'trace_samples');
   128  
   129          expect(df.format(month * 100, 100)).toBe('1.00 month');
   130          expect(df.format(44 * month * 100, 100)).toBe('44.00 months');
   131          expect(df.format(5.142 * month * 100, 100)).toBe('5.14 months');
   132          expect(df.format(0.88 * month * 100, 100)).toBe('0.88 months');
   133          expect(df.format(0.008 * month * 100, 100)).toBe('< 0.01 months');
   134          expect(df.formatPrecise(0.008 * month * 100, 100)).toBe('0.008 months');
   135        });
   136  
   137        it('correctly formats trace_samples duration when maxdur = year', () => {
   138          const year = 12 * 30 * 24 * 60 * 60;
   139          const df = getFormatter(year, 1, 'trace_samples');
   140  
   141          expect(df.format(year * 100, 100)).toBe('1.00 year');
   142          expect(df.format(12 * year * 100, 100)).toBe('12.00 years');
   143          expect(df.format(3.414 * year * 100, 100)).toBe('3.41 years');
   144          expect(df.format(0.12 * year * 100, 100)).toBe('0.12 years');
   145          expect(df.format(0.008 * year * 100, 100)).toBe('< 0.01 years');
   146          expect(df.formatPrecise(0.008 * year * 100, 100)).toBe('0.008 years');
   147        });
   148      });
   149  
   150      describe('ObjectsFormatter', () => {
   151        describe.each([
   152          [1, -1, '-1.00 '],
   153          [100_000, -1, '< 0.01 K'],
   154          [1_000_000, -1, '< 0.01 M'],
   155          [1_000_000_000, -1, '< 0.01 G'],
   156          [1_000_000_000_000, -1, '< 0.01 T'],
   157          [1_000_000_000_000_000, -1, '< 0.01 P'],
   158  
   159          [1, 1, '1.00 '],
   160          [100_000, 1, '< 0.01 K'],
   161          [1_000_000, 1, '< 0.01 M'],
   162          [1_000_000_000, 1, '< 0.01 G'],
   163          [1_000_000_000_000, 1, '< 0.01 T'],
   164          [1_000_000_000_000_000, 1, '< 0.01 P'],
   165  
   166          // if the tests here feel random, that's because they are
   167          // input and outputs were reproduced from real data
   168          [829449, 829449, '829.45 K'],
   169          [747270, 747270, '747.27 K'],
   170          [747270, 273208, '273.21 K'],
   171          [747270, 37257, '37.26 K'],
   172          [747270, 140789, '140.79 K'],
   173          [747270, 183646, '183.65 K'],
   174          [747270, 67736, '67.74 K'],
   175          [747270, 243513, '243.51 K'],
   176          [747270, 55297, '55.30 K'],
   177          [747270, 62261, '62.26 K'],
   178          [747270, 98304, '98.30 K'],
   179          [747270, 65536, '65.54 K'],
   180  
   181          [280614985, 124590057, '124.59 M'],
   182          [280614985, 15947382, '15.95 M'],
   183          [280614985, 15949534, '15.95 M'],
   184          [280614985, 23392042, '23.39 M'],
   185          [280614985, 100988801, '100.99 M'],
   186          [280614985, 280614985, '280.61 M'],
   187          [280614985, 30556974, '30.56 M'],
   188          [280614985, 51105740, '51.11 M'],
   189          [280614985, 92737376, '92.74 M'],
   190  
   191          [1536297877, 166358124, '0.17 G'],
   192          [1536297877, 94577307, '0.09 G'],
   193          [1536297877, 205971847, '0.21 G'],
   194          [1536297877, 245667926, '0.25 G'],
   195        ])(
   196          'new ObjectsFormatter(%i).format(%i, %i)',
   197          (maxObjects: number, samples: number, expected: string) => {
   198            it(`returns ${expected}`, () => {
   199              // sampleRate is not used
   200              const sampleRate = NaN;
   201              const f = getFormatter(maxObjects, sampleRate, 'objects');
   202  
   203              expect(f.format(samples, sampleRate)).toBe(expected);
   204            });
   205          }
   206        );
   207      });
   208  
   209      describe('ObjectsFormatter formatPrecise', () => {
   210        describe.each([
   211          [1, -1, '-1 '],
   212          [100_000, -1, '-0.001 K'],
   213  
   214          [1, 1, '1 '],
   215          [100_000, 1, '0.001 K'],
   216        ])(
   217          'new ObjectsFormatter(%i).format(%i, %i)',
   218          (maxObjects: number, samples: number, expected: string) => {
   219            it(`returns ${expected}`, () => {
   220              // sampleRate is not used
   221              const sampleRate = NaN;
   222              const f = getFormatter(maxObjects, sampleRate, 'objects');
   223  
   224              expect(f.formatPrecise(samples, sampleRate)).toBe(expected);
   225            });
   226          }
   227        );
   228      });
   229  
   230      describe('BytesFormatter', () => {
   231        describe.each([
   232          [1, -1, '-1.00 bytes'], // TODO is this correct?
   233          [1024, -1, '< 0.01 KB'],
   234          [1024 ** 2, -1, '< 0.01 MB'],
   235          [1024 ** 3, -1, '< 0.01 GB'],
   236          [1024 ** 4, -1, '< 0.01 TB'],
   237  
   238          [1, 1, '1.00 bytes'],
   239          [1024, 1, '< 0.01 KB'],
   240          [1024 ** 2, 1, '< 0.01 MB'],
   241          [1024 ** 3, 1, '< 0.01 GB'],
   242          [1024 ** 4, 1, '< 0.01 TB'],
   243  
   244          // if the tests here feel random, that's because they are
   245          // input and outputs were reproduced from real data
   246          [338855357, 269094260, '256.63 MB'],
   247          [338855357, 21498656, '20.50 MB'],
   248          [33261774660, 2369569091, '2.21 GB'],
   249          [33261774660, 12110767522, '11.28 GB'],
   250        ])(
   251          'new BytesFormatter(%i).format(%i, %i)',
   252          (maxObjects: number, samples: number, expected: string) => {
   253            it(`returns ${expected}`, () => {
   254              // sampleRate is not used
   255              const sampleRate = NaN;
   256              const f = getFormatter(maxObjects, sampleRate, 'bytes');
   257  
   258              expect(f.format(samples, sampleRate)).toBe(expected);
   259            });
   260          }
   261        );
   262      });
   263  
   264      describe('BytesFormatter', () => {
   265        describe.each([
   266          [1, -1, '-1 bytes'],
   267          [1024, -1, '-0.00098 KB'],
   268          [1024 ** 2, -10, '-0.00001 MB'],
   269          [1024 ** 3, -10000, '-0.00001 GB'],
   270          [1024 ** 4, -10000000, '-0.00001 TB'],
   271  
   272          [1, 1, '1 bytes'],
   273          [1024, 1, '0.00098 KB'],
   274          [1024 ** 2, 10, '0.00001 MB'],
   275          [1024 ** 3, 10000, '0.00001 GB'],
   276          [1024 ** 4, 10000000, '0.00001 TB'],
   277        ])(
   278          'new BytesFormatter(%i).format(%i, %i)',
   279          (maxObjects: number, samples: number, expected: string) => {
   280            it(`returns ${expected}`, () => {
   281              // sampleRate is not used
   282              const sampleRate = NaN;
   283              const f = getFormatter(maxObjects, sampleRate, 'bytes');
   284  
   285              expect(f.formatPrecise(samples, sampleRate)).toBe(expected);
   286            });
   287          }
   288        );
   289      });
   290    });
   291  });