You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: compact_test.go
    path of file: ./repos/pyroscope/pkg/phlaredb
    
    the code of the file until where you have to start completion: package phlaredb

import (
	"context"
	"fmt"
	_ "net/http/pprof"
	"os"
	"path/filepath"
	"sort"
	"testing"
	"time"

	"github.com/go-kit/log"
	"github.com/oklog/ulid"
	"github.com/parquet-go/parquet-go"
	"github.com/prometheus/common/model"
	"github.com/prometheus/prometheus/storage"
	"github.com/samber/lo"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

	ingesterv1 "github.com/grafana/pyroscope/api/gen/proto/go/ingester/v1"
	typesv1 "github.com/grafana/pyroscope/api/gen/proto/go/types/v1"
	phlaremodel "github.com/grafana/pyroscope/pkg/model"
	"github.com/grafana/pyroscope/pkg/objstore/client"
	"github.com/grafana/pyroscope/pkg/objstore/providers/filesystem"
	phlarecontext "github.com/grafana/pyroscope/pkg/phlare/context"
	"github.com/grafana/pyroscope/pkg/phlaredb/block"
	"github.com/grafana/pyroscope/pkg/phlaredb/sharding"
	"github.com/grafana/pyroscope/pkg/phlaredb/symdb"
	"github.com/grafana/pyroscope/pkg/phlaredb/tsdb/index"
	"github.com/grafana/pyroscope/pkg/pprof/testhelper"
)

func TestCompact(t *testing.T) {
	ctx := context.Background()
	b := newBlock(t, func() []*testhelper.ProfileBuilder {
		return []*testhelper.ProfileBuilder{
			testhelper.NewProfileBuilder(int64(time.Second*1)).
				CPUProfile().
				WithLabels(
					"job", "a",
				).ForStacktraceString("foo", "bar", "baz").AddSamples(1),
			testhelper.NewProfileBuilder(int64(time.Second*2)).
		
    
func TestCompactWithDownsampling(t *testing.T) {
	ctx := context.Background()
	b := newBlock(t, func() []*testhelper.ProfileBuilder {
		return []*testhelper.ProfileBuilder{
			testhelper.NewProfileBuilder(int64(time.Hour-time.Minute)).
				CPUProfile().
				WithLabels(
					"job", "a",
				).ForStacktraceString("foo", "bar", "baz").AddSamples(1),
			testhelper.NewProfileBuilder(int64(time.Hour+time.Minute)).
				CPUProfile().
				WithLabels(
					"job", "b",
				).ForStacktraceString("foo", "bar", "baz").AddSamples(1),
			testhelper.NewProfileBuilder(int64(time.Hour+6*time.Minute)).
				CPUProfile().
				WithLabels(
					"job", "c",
				).ForStacktraceString("foo", "bar", "baz").AddSamples(1),
		}
	})
	dst := t.TempDir()
	b.meta.Compaction.Level = 2
	compacted, err := Compact(ctx, []BlockReader{b, b, b, b}, dst)
	require.NoError(t, err)
	require.Equal(t, uint64(3), compacted.Stats.NumProfiles)
	require.Equal(t, uint64(3), compacted.Stats.NumSamples)
	require.Equal(t, uint64(3), compacted.Stats.NumSeries)
	require.Equal(t, model.Time((time.Hour - time.Minute).Milliseconds()), compacted.MinTime)
	require.Equal(t, model.Time((time.Hour + 6*time.Minute).Milliseconds()), compacted.MaxTime)

	for _, f := range []*block.File{
		compacted.FileByRelPath("profiles_5m_sum.parquet"),
		compacted.FileByRelPath("profiles_1h_sum.parquet"),
	} {
		require.NotNil(t, f)
		assert.NotZero(t, f.SizeBytes)
	}

	querier := blockQuerierFromMeta(t, dst, compacted)
	matchAll := &ingesterv1.SelectProfilesRequest{
		LabelSelector: "{}",
		Type:          mustParseProfileSelector(t, "process_cpu:cpu:nanoseconds:cpu:nanoseconds"),
		Start:         0,
		End:           (time.Hour + 7*time.Minute - time.Millisecond).Milliseconds(),
	}
	it, err := querier.SelectMatchingProfiles(ctx, matchAll)
	require.NoError(t, err)
	series, err := querier.MergeByLabels(ctx, it, nil, "job")
	require.NoError(t, err)
	require.Equal(t, []*typesv1.Series{
		{Labels: phlaremodel.LabelsFromStrings("job", "a"), Points: []*typesv1.Point{{Value: float64(1), Timestamp: (time.Hour - time.Minute).Milliseconds()}}},
		{Labels: phlaremodel.LabelsFromStrings("job", "b"), Points: []*typesv1.Point{{Value: float64(1), Timestamp: (time.Hour + time.Minute).Milliseconds()}}},
		{Labels: phlaremodel.LabelsFromStrings("job", "c"), Points: []*typesv1.Point{{Value: float64(1), Timestamp: (time.Hour + 6*time.Minute).Milliseconds()}}},
	}, series)

	it, err = querier.SelectMatchingProfiles(ctx, matchAll)
	require.NoError(t, err)
	res, err := querier.MergeByStacktraces(ctx, it)
	require.NoError(t, err)
	require.NotNil(t, res)

	expected := new(phlaremodel.Tree)
	expected.InsertStack(3, "baz", "bar", "foo")
	require.Equal(t, expected.String(), res.String())

	res, err = querier.SelectMergeByStacktraces(ctx, matchAll)
	require.NoError(t, err)
	require.NotNil(t, res)
	require.Equal(t, expected.String(), res.String())
	assert.False(t, querier.metrics.profileTableAccess.DeleteLabelValues(""))
	assert.True(t, querier.metrics.profileTableAccess.DeleteLabelValues("profiles_5m_sum.parquet"))
	assert.True(t, querier.metrics.profileTableAccess.DeleteLabelValues("profiles_1h_sum.parquet"))
	assert.True(t, querier.metrics.profileTableAccess.DeleteLabelValues("profiles.parquet"))
}