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 });