|
17 | 17 | */ |
18 | 18 |
|
19 | 19 | import { ProfileQuerier } from 'firefox-profiler/profile-query'; |
20 | | -import { getProfileFromTextSamples } from '../../fixtures/profiles/processed-profile'; |
| 20 | +import { |
| 21 | + getProfileFromTextSamples, |
| 22 | + getCounterForThread, |
| 23 | +} from '../../fixtures/profiles/processed-profile'; |
21 | 24 | import { getProfileRootRange } from 'firefox-profiler/selectors/profile'; |
22 | 25 | import { storeWithProfile } from '../../fixtures/stores'; |
23 | 26 |
|
@@ -344,6 +347,67 @@ describe('ProfileQuerier', function () { |
344 | 347 | }); |
345 | 348 | }); |
346 | 349 |
|
| 350 | + describe('counters', function () { |
| 351 | + function profileWithMemoryCounter() { |
| 352 | + const { profile } = getProfileFromTextSamples(` |
| 353 | + 0 1 2 |
| 354 | + A A A |
| 355 | + B B B |
| 356 | + `); |
| 357 | + const counter = getCounterForThread(profile.threads[0], 0, { |
| 358 | + name: 'malloc', |
| 359 | + category: 'Memory', |
| 360 | + hasCountNumber: true, |
| 361 | + }); |
| 362 | + profile.counters = [counter]; |
| 363 | + return { profile, counter }; |
| 364 | + } |
| 365 | + |
| 366 | + function querierFor(profile: Parameters<typeof storeWithProfile>[0]) { |
| 367 | + const store = storeWithProfile(profile); |
| 368 | + return new ProfileQuerier(store, getProfileRootRange(store.getState())); |
| 369 | + } |
| 370 | + |
| 371 | + it('counterList returns a schema-driven summary per counter', async function () { |
| 372 | + const { profile } = profileWithMemoryCounter(); |
| 373 | + const result = await querierFor(profile).counterList(); |
| 374 | + |
| 375 | + expect(result.counters).toHaveLength(1); |
| 376 | + expect(result.counters[0].counterHandle).toBe('c-0'); |
| 377 | + expect(result.counters[0].label).toBe('Memory'); |
| 378 | + expect( |
| 379 | + result.counters[0].stats.some((s) => s.source === 'count-range') |
| 380 | + ).toBe(true); |
| 381 | + }); |
| 382 | + |
| 383 | + it('profileInfo nests each counter under its owning process', async function () { |
| 384 | + const { profile, counter } = profileWithMemoryCounter(); |
| 385 | + const info = await querierFor(profile).profileInfo(); |
| 386 | + |
| 387 | + const owningProcess = info.processes.find((p) => p.pid === counter.pid); |
| 388 | + expect(owningProcess).toBeDefined(); |
| 389 | + expect(owningProcess!.counters?.map((c) => c.counterHandle)).toEqual([ |
| 390 | + 'c-0', |
| 391 | + ]); |
| 392 | + }); |
| 393 | + |
| 394 | + it('counterInfo resolves a counter by handle', async function () { |
| 395 | + const { profile } = profileWithMemoryCounter(); |
| 396 | + const info = await querierFor(profile).counterInfo('c-0'); |
| 397 | + |
| 398 | + expect(info.counterHandle).toBe('c-0'); |
| 399 | + expect(info.description).toBe('My Description'); |
| 400 | + expect(info.sampleCount).toBeGreaterThan(0); |
| 401 | + }); |
| 402 | + |
| 403 | + it('counterInfo throws for an unknown handle', async function () { |
| 404 | + const { profile } = profileWithMemoryCounter(); |
| 405 | + await expect(querierFor(profile).counterInfo('c-9')).rejects.toThrow( |
| 406 | + 'Unknown counter c-9' |
| 407 | + ); |
| 408 | + }); |
| 409 | + }); |
| 410 | + |
347 | 411 | describe('threadSamples', function () { |
348 | 412 | it('searches all roots when choosing the heaviest stack', async function () { |
349 | 413 | const { profile } = getProfileFromTextSamples(` |
|
0 commit comments