blob: 6eb6a7be7a57e082d3c1b1d0c0af729a86651224 [file]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
#include "util/block_budget.h"
#include <gtest/gtest.h>
namespace doris {
class BlockBudgetTest : public ::testing::Test {};
// ── effective_max_rows ──────────────────────────────────────────────────────
TEST_F(BlockBudgetTest, EffectiveMaxRowsNoByteBudget) {
BlockBudget b(4096, 0);
EXPECT_EQ(b.effective_max_rows(100), 4096);
EXPECT_EQ(b.effective_max_rows(0), 4096);
}
TEST_F(BlockBudgetTest, EffectiveMaxRowsZeroEstimate) {
BlockBudget b(4096, 8 * 1024 * 1024);
// When estimate is 0, fall back to max_rows.
EXPECT_EQ(b.effective_max_rows(0), 4096);
}
TEST_F(BlockBudgetTest, EffectiveMaxRowsByteLimited) {
// 8 MB budget, 10 KB per row → 819 rows (< 4096 max_rows)
BlockBudget b(4096, 8 * 1024 * 1024);
EXPECT_EQ(b.effective_max_rows(10 * 1024), 819);
}
TEST_F(BlockBudgetTest, EffectiveMaxRowsRowLimited) {
// 8 MB budget, 10 bytes per row → 838860 rows, but max_rows = 4096
BlockBudget b(4096, 8 * 1024 * 1024);
EXPECT_EQ(b.effective_max_rows(10), 4096);
}
TEST_F(BlockBudgetTest, EffectiveMaxRowsReturnsAtLeastOne) {
// Huge rows: 100 MB per row, 8 MB budget → 0, but clamped to 1
BlockBudget b(4096, 8 * 1024 * 1024);
EXPECT_EQ(b.effective_max_rows(100 * 1024 * 1024), 1);
}
// ── within_budget / exceeded ────────────────────────────────────────────────
TEST_F(BlockBudgetTest, WithinBudgetNoByteBudget) {
BlockBudget b(100, 0);
EXPECT_TRUE(b.within_budget(0, 0));
EXPECT_TRUE(b.within_budget(99, 999999999));
EXPECT_FALSE(b.within_budget(100, 0));
EXPECT_FALSE(b.within_budget(200, 0));
}
TEST_F(BlockBudgetTest, WithinBudgetWithByteBudget) {
BlockBudget b(100, 1000);
EXPECT_TRUE(b.within_budget(50, 500)); // both under
EXPECT_FALSE(b.within_budget(100, 500)); // rows hit
EXPECT_FALSE(b.within_budget(50, 1000)); // bytes hit
EXPECT_FALSE(b.within_budget(100, 1000)); // both hit
}
TEST_F(BlockBudgetTest, ExceededIsInverseOfWithinBudget) {
BlockBudget b(100, 1000);
// Note: exceeded uses >=, within_budget uses <, so they should be
// perfect logical inverses.
for (size_t r : {0, 50, 99, 100, 200}) {
for (size_t bytes : {0, 500, 999, 1000, 2000}) {
EXPECT_EQ(b.exceeded(r, bytes), !b.within_budget(r, bytes))
<< "r=" << r << " bytes=" << bytes;
}
}
}
// ── remaining_rows ──────────────────────────────────────────────────────────
TEST_F(BlockBudgetTest, RemainingRowsNoByteBudget) {
BlockBudget b(100, 0);
EXPECT_EQ(b.remaining_rows(0, 0), 100);
EXPECT_EQ(b.remaining_rows(60, 9999), 40);
EXPECT_EQ(b.remaining_rows(100, 0), 0);
EXPECT_EQ(b.remaining_rows(200, 0), 0);
}
TEST_F(BlockBudgetTest, RemainingRowsByteLimited) {
// max_rows=100, max_bytes=1000, current: 50 rows, 600 bytes
// avg = 12 bytes/row, byte_capacity = (1000-600)/12 = 33
// row_capacity = 100 - 50 = 50
// result = min(50, 33) = 33
BlockBudget b(100, 1000);
EXPECT_EQ(b.remaining_rows(50, 600), 33);
}
TEST_F(BlockBudgetTest, RemainingRowsAlreadyOverByteBudget) {
BlockBudget b(100, 1000);
EXPECT_EQ(b.remaining_rows(50, 1000), 0);
EXPECT_EQ(b.remaining_rows(50, 2000), 0);
}
TEST_F(BlockBudgetTest, RemainingRowsZeroCurrentRows) {
// No rows yet → can't estimate avg_row_bytes, fall back to row capacity
BlockBudget b(100, 1000);
EXPECT_EQ(b.remaining_rows(0, 0), 100);
}
TEST_F(BlockBudgetTest, RemainingRowsZeroCurrentBytes) {
// Has rows but zero bytes → can't estimate avg, fall back to row capacity
BlockBudget b(100, 1000);
EXPECT_EQ(b.remaining_rows(50, 0), 50);
}
} // namespace doris