Skip to content

Commit f623919

Browse files
authored
Reuse native histogram test functions from Prometheus (#6059)
* reuse native histogram test functions from Prometheus Signed-off-by: Ben Ye <[email protected]> * lint Signed-off-by: Ben Ye <[email protected]> --------- Signed-off-by: Ben Ye <[email protected]>
1 parent 9965352 commit f623919

File tree

10 files changed

+48
-115
lines changed

10 files changed

+48
-115
lines changed

integration/e2e/util.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ import (
2121
"github.com/prometheus/prometheus/storage"
2222
"github.com/prometheus/prometheus/storage/remote"
2323
"github.com/prometheus/prometheus/tsdb"
24+
"github.com/prometheus/prometheus/tsdb/tsdbutil"
2425
"github.com/thanos-io/thanos/pkg/block/metadata"
2526
"github.com/thanos-io/thanos/pkg/runutil"
2627

2728
cortex_tsdb "github.com/cortexproject/cortex/pkg/storage/tsdb"
28-
histogram_util "github.com/cortexproject/cortex/pkg/util/histogram"
2929
)
3030

3131
func RunCommandAndGetOutput(name string, args ...string) ([]byte, error) {
@@ -174,10 +174,10 @@ func GenerateHistogramSeries(name string, ts time.Time, floatHistogram bool, add
174174
ph prompb.Histogram
175175
)
176176
if floatHistogram {
177-
fh = histogram_util.GenerateTestFloatHistogram(int(i))
177+
fh = tsdbutil.GenerateTestFloatHistogram(int(i))
178178
ph = remote.FloatHistogramToHistogramProto(tsMillis, fh)
179179
} else {
180-
h = histogram_util.GenerateTestHistogram(int(i))
180+
h = tsdbutil.GenerateTestHistogram(int(i))
181181
ph = remote.HistogramToHistogramProto(tsMillis, h)
182182
}
183183

pkg/distributor/distributor_test.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/prometheus/prometheus/model/labels"
2424
"github.com/prometheus/prometheus/model/relabel"
2525
"github.com/prometheus/prometheus/tsdb/chunkenc"
26+
"github.com/prometheus/prometheus/tsdb/tsdbutil"
2627
"github.com/stretchr/testify/assert"
2728
"github.com/stretchr/testify/require"
2829
"github.com/weaveworks/common/httpgrpc"
@@ -45,7 +46,6 @@ import (
4546
"github.com/cortexproject/cortex/pkg/util"
4647
"github.com/cortexproject/cortex/pkg/util/chunkcompat"
4748
"github.com/cortexproject/cortex/pkg/util/flagext"
48-
histogram_util "github.com/cortexproject/cortex/pkg/util/histogram"
4949
"github.com/cortexproject/cortex/pkg/util/limiter"
5050
"github.com/cortexproject/cortex/pkg/util/services"
5151
"github.com/cortexproject/cortex/pkg/util/test"
@@ -2643,7 +2643,7 @@ func mockWriteRequest(lbls []labels.Labels, value int64, timestampMs int64, hist
26432643
if histogram {
26442644
histograms = make([]cortexpb.Histogram, len(lbls))
26452645
for i := range lbls {
2646-
histograms[i] = cortexpb.HistogramToHistogramProto(timestampMs, histogram_util.GenerateTestHistogram(int(value)))
2646+
histograms[i] = cortexpb.HistogramToHistogramProto(timestampMs, tsdbutil.GenerateTestHistogram(int(value)))
26472647
}
26482648
} else {
26492649
samples = make([]cortexpb.Sample, len(lbls))
@@ -2882,7 +2882,7 @@ func makeWriteRequestTimeseries(labels []cortexpb.LabelAdapter, ts int64, value
28822882
},
28832883
}
28842884
if histogram {
2885-
t.Histograms = append(t.Histograms, cortexpb.HistogramToHistogramProto(ts, histogram_util.GenerateTestHistogram(value)))
2885+
t.Histograms = append(t.Histograms, cortexpb.HistogramToHistogramProto(ts, tsdbutil.GenerateTestHistogram(value)))
28862886
} else {
28872887
t.Samples = append(t.Samples, cortexpb.Sample{
28882888
TimestampMs: ts,
@@ -2908,7 +2908,7 @@ func makeWriteRequestHA(samples int, replica, cluster string, histogram bool) *c
29082908
}
29092909
if histogram {
29102910
ts.Histograms = []cortexpb.Histogram{
2911-
cortexpb.HistogramToHistogramProto(int64(i), histogram_util.GenerateTestHistogram(i)),
2911+
cortexpb.HistogramToHistogramProto(int64(i), tsdbutil.GenerateTestHistogram(i)),
29122912
}
29132913
} else {
29142914
ts.Samples = []cortexpb.Sample{
@@ -3354,8 +3354,8 @@ func TestDistributorValidation(t *testing.T) {
33543354
ctx := user.InjectOrgID(context.Background(), "1")
33553355
now := model.Now()
33563356
future, past := now.Add(5*time.Hour), now.Add(-25*time.Hour)
3357-
testHistogram := histogram_util.GenerateTestHistogram(1)
3358-
testFloatHistogram := histogram_util.GenerateTestFloatHistogram(1)
3357+
testHistogram := tsdbutil.GenerateTestHistogram(1)
3358+
testFloatHistogram := tsdbutil.GenerateTestFloatHistogram(1)
33593359

33603360
for i, tc := range []struct {
33613361
metadata []*cortexpb.MetricMetadata

pkg/ingester/ingester_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import (
3131
"github.com/prometheus/prometheus/storage"
3232
"github.com/prometheus/prometheus/tsdb"
3333
"github.com/prometheus/prometheus/tsdb/chunkenc"
34+
"github.com/prometheus/prometheus/tsdb/tsdbutil"
3435
"github.com/stretchr/testify/assert"
3536
"github.com/stretchr/testify/mock"
3637
"github.com/stretchr/testify/require"
@@ -53,7 +54,6 @@ import (
5354
"github.com/cortexproject/cortex/pkg/storage/tsdb/bucketindex"
5455
"github.com/cortexproject/cortex/pkg/util"
5556
"github.com/cortexproject/cortex/pkg/util/chunkcompat"
56-
histogram_util "github.com/cortexproject/cortex/pkg/util/histogram"
5757
"github.com/cortexproject/cortex/pkg/util/services"
5858
"github.com/cortexproject/cortex/pkg/util/test"
5959
"github.com/cortexproject/cortex/pkg/util/validation"
@@ -658,8 +658,8 @@ func TestIngester_Push(t *testing.T) {
658658
}
659659
userID := "test"
660660

661-
testHistogram := cortexpb.HistogramToHistogramProto(10, histogram_util.GenerateTestHistogram(1))
662-
testFloatHistogram := cortexpb.FloatHistogramToHistogramProto(11, histogram_util.GenerateTestFloatHistogram(1))
661+
testHistogram := cortexpb.HistogramToHistogramProto(10, tsdbutil.GenerateTestHistogram(1))
662+
testFloatHistogram := cortexpb.FloatHistogramToHistogramProto(11, tsdbutil.GenerateTestFloatHistogram(1))
663663
tests := map[string]struct {
664664
reqs []*cortexpb.WriteRequest
665665
expectedErr error
@@ -953,7 +953,7 @@ func TestIngester_Push(t *testing.T) {
953953
[]cortexpb.Sample{{Value: 1, TimestampMs: 9}},
954954
nil,
955955
[]cortexpb.Histogram{
956-
cortexpb.HistogramToHistogramProto(9, histogram_util.GenerateTestHistogram(1)),
956+
cortexpb.HistogramToHistogramProto(9, tsdbutil.GenerateTestHistogram(1)),
957957
},
958958
cortexpb.API),
959959
},
@@ -1012,7 +1012,7 @@ func TestIngester_Push(t *testing.T) {
10121012
[]cortexpb.Sample{{Value: 1, TimestampMs: 1575043969 - (86400 * 1000)}},
10131013
nil,
10141014
[]cortexpb.Histogram{
1015-
cortexpb.HistogramToHistogramProto(1575043969-(86400*1000), histogram_util.GenerateTestHistogram(1)),
1015+
cortexpb.HistogramToHistogramProto(1575043969-(86400*1000), tsdbutil.GenerateTestHistogram(1)),
10161016
},
10171017
cortexpb.API),
10181018
},
@@ -3153,13 +3153,13 @@ func mockHistogramWriteRequest(t *testing.T, lbls labels.Labels, value int, time
31533153
c chunkenc.Chunk
31543154
)
31553155
if float {
3156-
fh = histogram_util.GenerateTestFloatHistogram(value)
3156+
fh = tsdbutil.GenerateTestFloatHistogram(value)
31573157
histograms = []cortexpb.Histogram{
31583158
cortexpb.FloatHistogramToHistogramProto(timestampMs, fh),
31593159
}
31603160
c = chunkenc.NewFloatHistogramChunk()
31613161
} else {
3162-
h = histogram_util.GenerateTestHistogram(value)
3162+
h = tsdbutil.GenerateTestHistogram(value)
31633163
histograms = []cortexpb.Histogram{
31643164
cortexpb.HistogramToHistogramProto(timestampMs, h),
31653165
}

pkg/querier/batch/batch_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ func BenchmarkNewChunkMergeIterator_Seek(b *testing.B) {
121121
}
122122

123123
func TestSeekCorrectlyDealWithSinglePointChunks(t *testing.T) {
124-
histograms := histogram_util.GenerateTestHistograms(1000, 1000, 1, 5, 20)
124+
histograms := histogram_util.GenerateTestHistograms(1000, 1000, 1)
125125
for _, enc := range []promchunk.Encoding{
126126
promchunk.PrometheusXorChunk,
127127
promchunk.PrometheusHistogramChunk,

pkg/querier/batch/chunk_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ func mkGenericChunk(t require.TestingT, from model.Time, points int, enc promchu
5353
}
5454

5555
func testIter(t require.TestingT, points int, iter chunkenc.Iterator, enc promchunk.Encoding) {
56-
histograms := histogram_util.GenerateTestHistograms(0, 1000, points, 5, 20)
56+
histograms := histogram_util.GenerateTestHistograms(0, 1000, points)
5757
ets := model.TimeFromUnix(0)
5858
for i := 0; i < points; i++ {
5959
require.Equal(t, iter.Next(), enc.ChunkValueType(), strconv.Itoa(i))
@@ -77,7 +77,7 @@ func testIter(t require.TestingT, points int, iter chunkenc.Iterator, enc promch
7777
}
7878

7979
func testSeek(t require.TestingT, points int, iter chunkenc.Iterator, enc promchunk.Encoding) {
80-
histograms := histogram_util.GenerateTestHistograms(0, 1000, points, 5, 20)
80+
histograms := histogram_util.GenerateTestHistograms(0, 1000, points)
8181
for i := 0; i < points; i += points / 10 {
8282
ets := int64(i * int(step/time.Millisecond))
8383

pkg/querier/blocks_store_queryable_test.go

+9-12
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"github.com/prometheus/prometheus/promql"
2222
"github.com/prometheus/prometheus/storage"
2323
"github.com/prometheus/prometheus/tsdb/chunkenc"
24+
"github.com/prometheus/prometheus/tsdb/tsdbutil"
2425
"github.com/stretchr/testify/assert"
2526
"github.com/stretchr/testify/mock"
2627
"github.com/stretchr/testify/require"
@@ -41,7 +42,6 @@ import (
4142
"github.com/cortexproject/cortex/pkg/storegateway"
4243
"github.com/cortexproject/cortex/pkg/storegateway/storegatewaypb"
4344
"github.com/cortexproject/cortex/pkg/util"
44-
histogram_util "github.com/cortexproject/cortex/pkg/util/histogram"
4545
"github.com/cortexproject/cortex/pkg/util/limiter"
4646
"github.com/cortexproject/cortex/pkg/util/services"
4747
"github.com/cortexproject/cortex/pkg/util/validation"
@@ -65,12 +65,12 @@ func TestBlocksStoreQuerier_Select(t *testing.T) {
6565
series1Label = labels.Label{Name: "series", Value: "1"}
6666
series2Label = labels.Label{Name: "series", Value: "2"}
6767
noOpQueryLimiter = limiter.NewQueryLimiter(0, 0, 0, 0)
68-
testHistogram1 = histogram_util.GenerateTestHistogram(1)
69-
testHistogram2 = histogram_util.GenerateTestHistogram(2)
70-
testHistogram3 = histogram_util.GenerateTestHistogram(3)
71-
testFloatHistogram1 = histogram_util.GenerateTestFloatHistogram(1)
72-
testFloatHistogram2 = histogram_util.GenerateTestFloatHistogram(2)
73-
testFloatHistogram3 = histogram_util.GenerateTestFloatHistogram(3)
68+
testHistogram1 = tsdbutil.GenerateTestHistogram(1)
69+
testHistogram2 = tsdbutil.GenerateTestHistogram(2)
70+
testHistogram3 = tsdbutil.GenerateTestHistogram(3)
71+
testFloatHistogram1 = tsdbutil.GenerateTestFloatHistogram(1)
72+
testFloatHistogram2 = tsdbutil.GenerateTestFloatHistogram(2)
73+
testFloatHistogram3 = tsdbutil.GenerateTestFloatHistogram(3)
7474
)
7575

7676
type valueResult struct {
@@ -2279,13 +2279,10 @@ func TestBlocksStoreQuerier_PromQLExecution(t *testing.T) {
22792279
h := h
22802280
// Check sample timestamp is expected.
22812281
require.Equal(t, h.T, int64(from)+int64(i)*15000)
2282+
expectedH := tsdbutil.GenerateTestGaugeFloatHistogram(int(h.T))
22822283
if enc == encoding.PrometheusHistogramChunk {
2283-
// GenerateTestHistogram will add 10 for the input value i so subtract 10 here.
2284-
expectedH := histogram_util.GenerateTestHistogram(int(h.T - 10))
2285-
require.Equal(t, expectedH.ToFloat(nil), h.H)
2284+
require.Equal(t, expectedH, h.H)
22862285
} else if enc == encoding.PrometheusFloatHistogramChunk {
2287-
// GenerateTestHistogram will add 10 for the input value i so subtract 10 here.
2288-
expectedH := histogram_util.GenerateTestFloatHistogram(int(h.T - 10))
22892286
require.Equal(t, expectedH, h.H)
22902287
}
22912288
}

pkg/querier/querier_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/prometheus/prometheus/promql"
1919
"github.com/prometheus/prometheus/scrape"
2020
"github.com/prometheus/prometheus/storage"
21+
"github.com/prometheus/prometheus/tsdb/tsdbutil"
2122
"github.com/prometheus/prometheus/util/annotations"
2223
"github.com/stretchr/testify/assert"
2324
"github.com/stretchr/testify/mock"
@@ -34,7 +35,6 @@ import (
3435
"github.com/cortexproject/cortex/pkg/util"
3536
"github.com/cortexproject/cortex/pkg/util/chunkcompat"
3637
"github.com/cortexproject/cortex/pkg/util/flagext"
37-
histogram_util "github.com/cortexproject/cortex/pkg/util/histogram"
3838
"github.com/cortexproject/cortex/pkg/util/validation"
3939
)
4040

@@ -140,7 +140,7 @@ var (
140140
for i, point := range series.Histograms {
141141
require.Equal(t, ts, point.T, strconv.Itoa(i))
142142
// Convert expected value to float histogram.
143-
expectedH := histogram_util.GenerateTestFloatHistogram(int(ts - 10))
143+
expectedH := tsdbutil.GenerateTestGaugeFloatHistogram(int(ts))
144144
require.Equal(t, expectedH, point.H, strconv.Itoa(i))
145145
ts += int64(q.step / time.Millisecond)
146146
}
@@ -202,7 +202,7 @@ var (
202202
for i, point := range series.Histograms {
203203
require.Equal(t, ts, point.T, strconv.Itoa(i))
204204
// Convert expected value to float histogram.
205-
expectedH := histogram_util.GenerateTestFloatHistogram(int(ts - 10))
205+
expectedH := tsdbutil.GenerateTestGaugeFloatHistogram(int(ts))
206206
require.Equal(t, expectedH, point.H, strconv.Itoa(i))
207207
ts += int64(q.step / time.Millisecond)
208208
}
@@ -222,7 +222,7 @@ var (
222222
from, through := time.Unix(0, 0), end.Time()
223223
require.Equal(t, q.samples(from, through, q.step), len(series.Floats))
224224
for i, point := range series.Floats {
225-
expectedFH := histogram_util.GenerateTestFloatHistogram(int(ts - 10))
225+
expectedFH := tsdbutil.GenerateTestFloatHistogram(int(ts))
226226
require.Equal(t, ts, point.T, strconv.Itoa(i))
227227
require.Equal(t, expectedFH.Sum, point.F, strconv.Itoa(i))
228228
ts += int64(q.step / time.Millisecond)
@@ -243,7 +243,7 @@ var (
243243
from, through := time.Unix(0, 0), end.Time()
244244
require.Equal(t, q.samples(from, through, q.step), len(series.Floats))
245245
for i, point := range series.Floats {
246-
expectedFH := histogram_util.GenerateTestFloatHistogram(int(ts - 10))
246+
expectedFH := tsdbutil.GenerateTestFloatHistogram(int(ts))
247247
require.Equal(t, ts, point.T, strconv.Itoa(i))
248248
require.Equal(t, expectedFH.Count, point.F, strconv.Itoa(i))
249249
ts += int64(q.step / time.Millisecond)

pkg/ruler/compat_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ import (
1818
"github.com/prometheus/prometheus/model/value"
1919
"github.com/prometheus/prometheus/promql"
2020
"github.com/prometheus/prometheus/promql/parser"
21+
"github.com/prometheus/prometheus/tsdb/tsdbutil"
2122
"github.com/stretchr/testify/require"
2223
"github.com/weaveworks/common/httpgrpc"
2324

2425
"github.com/cortexproject/cortex/pkg/cortexpb"
25-
histogram_util "github.com/cortexproject/cortex/pkg/util/histogram"
2626
"github.com/cortexproject/cortex/pkg/util/validation"
2727
)
2828

@@ -45,10 +45,10 @@ func TestPusherAppendable(t *testing.T) {
4545
lbls2 := cortexpb.FromLabelsToLabelAdapters(labels.FromMap(map[string]string{labels.MetricName: "ALERTS", labels.AlertName: "boop"}))
4646
lbls3 := cortexpb.FromLabelsToLabelAdapters(labels.FromMap(map[string]string{labels.MetricName: "ALERTS_FOR_STATE", labels.AlertName: "boop"}))
4747

48-
testHistogram := histogram_util.GenerateTestHistogram(1)
49-
testFloatHistogram := histogram_util.GenerateTestFloatHistogram(2)
50-
testHistogramWithNaN := histogram_util.GenerateTestHistogram(1)
51-
testFloatHistogramWithNaN := histogram_util.GenerateTestFloatHistogram(1)
48+
testHistogram := tsdbutil.GenerateTestHistogram(1)
49+
testFloatHistogram := tsdbutil.GenerateTestFloatHistogram(2)
50+
testHistogramWithNaN := tsdbutil.GenerateTestHistogram(1)
51+
testFloatHistogramWithNaN := tsdbutil.GenerateTestFloatHistogram(1)
5252
testHistogramWithNaN.Sum = math.Float64frombits(value.StaleNaN)
5353
testFloatHistogramWithNaN.Sum = math.Float64frombits(value.StaleNaN)
5454

@@ -470,9 +470,9 @@ func TestPusherErrors(t *testing.T) {
470470
_, err = a.Append(0, lbls, int64(model.Now()), 123456)
471471
require.NoError(t, err)
472472

473-
_, err = a.AppendHistogram(0, lbls, int64(model.Now()), histogram_util.GenerateTestHistogram(1), nil)
473+
_, err = a.AppendHistogram(0, lbls, int64(model.Now()), tsdbutil.GenerateTestHistogram(1), nil)
474474
require.NoError(t, err)
475-
_, err = a.AppendHistogram(0, lbls, int64(model.Now()), nil, histogram_util.GenerateTestFloatHistogram(2))
475+
_, err = a.AppendHistogram(0, lbls, int64(model.Now()), nil, tsdbutil.GenerateTestFloatHistogram(2))
476476
require.NoError(t, err)
477477

478478
require.Equal(t, tc.returnedError, a.Commit())

pkg/util/histogram/testutils.go

+6-70
Original file line numberDiff line numberDiff line change
@@ -13,81 +13,17 @@
1313

1414
package histogram
1515

16-
import "github.com/prometheus/prometheus/model/histogram"
16+
import (
17+
"github.com/prometheus/prometheus/model/histogram"
18+
"github.com/prometheus/prometheus/tsdb/tsdbutil"
19+
)
1720

1821
// Adapted from Prometheus model/histogram/test_utils.go GenerateBigTestHistograms.
19-
func GenerateTestHistograms(from, step, numHistograms, numSpans, numBuckets int) []*histogram.Histogram {
20-
bucketsPerSide := numBuckets / 2
21-
spanLength := uint32(bucketsPerSide / numSpans)
22-
// Given all bucket deltas are 1, sum bucketsPerSide + 1.
23-
observationCount := bucketsPerSide * (1 + bucketsPerSide)
24-
22+
func GenerateTestHistograms(from, step, numHistograms int) []*histogram.Histogram {
2523
var histograms []*histogram.Histogram
2624
for i := 0; i < numHistograms; i++ {
2725
v := from + i*step
28-
h := &histogram.Histogram{
29-
CounterResetHint: histogram.GaugeType,
30-
Count: uint64(v + observationCount),
31-
ZeroCount: uint64(v),
32-
ZeroThreshold: 1e-128,
33-
Sum: 18.4 * float64(v+1),
34-
Schema: 2,
35-
NegativeSpans: make([]histogram.Span, numSpans),
36-
PositiveSpans: make([]histogram.Span, numSpans),
37-
NegativeBuckets: make([]int64, bucketsPerSide),
38-
PositiveBuckets: make([]int64, bucketsPerSide),
39-
}
40-
41-
for j := 0; j < numSpans; j++ {
42-
s := histogram.Span{Offset: 1, Length: spanLength}
43-
h.NegativeSpans[j] = s
44-
h.PositiveSpans[j] = s
45-
}
46-
47-
for j := 0; j < bucketsPerSide; j++ {
48-
h.NegativeBuckets[j] = 1
49-
h.PositiveBuckets[j] = 1
50-
}
51-
52-
histograms = append(histograms, h)
26+
histograms = append(histograms, tsdbutil.GenerateTestGaugeHistogram(v))
5327
}
5428
return histograms
5529
}
56-
57-
func GenerateTestHistogram(i int) *histogram.Histogram {
58-
bucketsPerSide := 10
59-
spanLength := uint32(2)
60-
// Given all bucket deltas are 1, sum bucketsPerSide + 1.
61-
observationCount := bucketsPerSide * (1 + bucketsPerSide)
62-
63-
v := 10 + i
64-
h := &histogram.Histogram{
65-
CounterResetHint: histogram.GaugeType,
66-
Count: uint64(v + observationCount),
67-
ZeroCount: uint64(v),
68-
ZeroThreshold: 1e-128,
69-
Sum: 18.4 * float64(v+1),
70-
Schema: 2,
71-
NegativeSpans: make([]histogram.Span, 5),
72-
PositiveSpans: make([]histogram.Span, 5),
73-
NegativeBuckets: make([]int64, bucketsPerSide),
74-
PositiveBuckets: make([]int64, bucketsPerSide),
75-
}
76-
77-
for j := 0; j < 5; j++ {
78-
s := histogram.Span{Offset: 1, Length: spanLength}
79-
h.NegativeSpans[j] = s
80-
h.PositiveSpans[j] = s
81-
}
82-
83-
for j := 0; j < bucketsPerSide; j++ {
84-
h.NegativeBuckets[j] = 1
85-
h.PositiveBuckets[j] = 1
86-
}
87-
88-
return h
89-
}
90-
91-
func GenerateTestFloatHistogram(i int) *histogram.FloatHistogram {
92-
return GenerateTestHistogram(i).ToFloat(nil)
93-
}

0 commit comments

Comments
 (0)