Procházet zdrojové kódy

Fix panic on merge when one profile missing mappings (#291)

* Fix panic on merge when one profile missing mappings

* Simplify fix for merge panics
Margaret Nolan před 7 roky
rodič
revize
e9167955d7
No account linked to committer's email address
2 změnil soubory, kde provedl 89 přidání a 1 odebrání
  1. 1
    1
      profile/merge.go
  2. 88
    0
      profile/profile_test.go

+ 1
- 1
profile/merge.go Zobrazit soubor

@@ -64,7 +64,7 @@ func Merge(srcs []*Profile) (*Profile, error) {
64 64
 			// represents the main binary. Take the first Mapping we see,
65 65
 			// otherwise the operations below will add mappings in an
66 66
 			// arbitrary order.
67
-			pm.mapMapping(srcs[0].Mapping[0])
67
+			pm.mapMapping(src.Mapping[0])
68 68
 		}
69 69
 
70 70
 		for _, s := range src.Sample {

+ 88
- 0
profile/profile_test.go Zobrazit soubor

@@ -330,6 +330,60 @@ var testProfile1 = &Profile{
330 330
 	Mapping:  cpuM,
331 331
 }
332 332
 
333
+var testProfile1NoMapping = &Profile{
334
+	PeriodType:    &ValueType{Type: "cpu", Unit: "milliseconds"},
335
+	Period:        1,
336
+	DurationNanos: 10e9,
337
+	SampleType: []*ValueType{
338
+		{Type: "samples", Unit: "count"},
339
+		{Type: "cpu", Unit: "milliseconds"},
340
+	},
341
+	Sample: []*Sample{
342
+		{
343
+			Location: []*Location{cpuL[0]},
344
+			Value:    []int64{1000, 1000},
345
+			Label: map[string][]string{
346
+				"key1": {"tag1"},
347
+				"key2": {"tag1"},
348
+			},
349
+		},
350
+		{
351
+			Location: []*Location{cpuL[1], cpuL[0]},
352
+			Value:    []int64{100, 100},
353
+			Label: map[string][]string{
354
+				"key1": {"tag2"},
355
+				"key3": {"tag2"},
356
+			},
357
+		},
358
+		{
359
+			Location: []*Location{cpuL[2], cpuL[0]},
360
+			Value:    []int64{10, 10},
361
+			Label: map[string][]string{
362
+				"key1": {"tag3"},
363
+				"key2": {"tag2"},
364
+			},
365
+		},
366
+		{
367
+			Location: []*Location{cpuL[3], cpuL[0]},
368
+			Value:    []int64{10000, 10000},
369
+			Label: map[string][]string{
370
+				"key1": {"tag4"},
371
+				"key2": {"tag1"},
372
+			},
373
+		},
374
+		{
375
+			Location: []*Location{cpuL[4], cpuL[0]},
376
+			Value:    []int64{1, 1},
377
+			Label: map[string][]string{
378
+				"key1": {"tag4"},
379
+				"key2": {"tag1"},
380
+			},
381
+		},
382
+	},
383
+	Location: cpuL,
384
+	Function: cpuF,
385
+}
386
+
333 387
 var testProfile2 = &Profile{
334 388
 	PeriodType:    &ValueType{Type: "cpu", Unit: "milliseconds"},
335 389
 	Period:        1,
@@ -684,6 +738,40 @@ func TestNumLabelMerge(t *testing.T) {
684 738
 	}
685 739
 }
686 740
 
741
+func TestEmptyMappingMerge(t *testing.T) {
742
+	// Aggregate a profile with itself and once again with a factor of
743
+	// -2. Should end up with an empty profile (all samples for a
744
+	// location should add up to 0).
745
+
746
+	prof1 := testProfile1.Copy()
747
+	prof2 := testProfile1NoMapping.Copy()
748
+	p1, err := Merge([]*Profile{prof2, prof1})
749
+	if err != nil {
750
+		t.Errorf("merge error: %v", err)
751
+	}
752
+	prof2.Scale(-2)
753
+	prof, err := Merge([]*Profile{p1, prof2})
754
+	if err != nil {
755
+		t.Errorf("merge error: %v", err)
756
+	}
757
+
758
+	// Use aggregation to merge locations at function granularity.
759
+	if err := prof.Aggregate(false, true, false, false, false); err != nil {
760
+		t.Errorf("aggregating after merge: %v", err)
761
+	}
762
+
763
+	samples := make(map[string]int64)
764
+	for _, s := range prof.Sample {
765
+		tb := locationHash(s)
766
+		samples[tb] = samples[tb] + s.Value[0]
767
+	}
768
+	for s, v := range samples {
769
+		if v != 0 {
770
+			t.Errorf("nonzero value for sample %s: %d", s, v)
771
+		}
772
+	}
773
+}
774
+
687 775
 func TestNormalizeBySameProfile(t *testing.T) {
688 776
 	pb := testProfile1.Copy()
689 777
 	p := testProfile1.Copy()