blob: 5e737be8f1586e71d23eab81514e40961eb8aa66 [file] [log] [blame]
// Copyright 2017-2020 The Verible Authors.
//
// Licensed 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 "verilog/formatting/formatter.h"
// prevent header re-ordering
#include <sstream>
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "common/strings/position.h"
#include "common/util/logging.h"
#include "verilog/formatting/format_style.h"
#undef EXPECT_OK
#define EXPECT_OK(value) EXPECT_TRUE((value).ok())
#undef ASSERT_OK
#define ASSERT_OK(value) ASSERT_TRUE((value).ok())
namespace verilog {
namespace formatter {
namespace {
struct FormatterTestCase {
absl::string_view input;
absl::string_view expected;
};
static const verible::LineNumberSet kEnableAllLines;
// Tests in this file are intended to be sensitive to wrapping penalty tuning.
// These test cases should be kept short, small enough to be directed
// at particular desirable characteristics.
// TODO(b/145558510): these tests must maintain unique-best solutions
static constexpr FormatterTestCase kTestCases[] = {
//----------- 40 column marker --------->|
{// TODO(b/148972363): might want to attract "= sss(" more
"module m;"
"assign wwwwww[77:66]"
"= sss(qqqq[33:22],"
"vv[44:1]);"
"endmodule",
"module m;\n"
" assign wwwwww[77:66] = sss(\n"
" qqqq[33:22], vv[44:1]\n"
" );\n"
"endmodule\n"},
{"module m;\n"
"localparam int foo = xxxxxxxxxx + yyyyyyyyyyyyyy + zzzzzzzzzzz;\n"
"endmodule\n",
"module m;\n"
" localparam int foo = xxxxxxxxxx +\n"
" yyyyyyyyyyyyyy + zzzzzzzzzzz;\n"
"endmodule\n"},
};
// These formatter tests involve line wrapping and hence line-wrap penalty
// tuning. Keep these short and minimal where possible.
TEST(FormatterEndToEndTest, PenaltySensitiveLineWrapping) {
// Use a fixed style.
FormatStyle style;
style.column_limit = 40;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
for (const auto& test_case : kTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream, debug_stream;
ExecutionControl control;
control.stream = &debug_stream;
const auto status = FormatVerilog(test_case.input, "<filename>", style,
stream, kEnableAllLines, control);
EXPECT_OK(status);
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
EXPECT_TRUE(debug_stream.str().empty());
}
}
// Sometimes it's hard to reduce a real test case to a 40 column version,
// so this set of tests uses 100-column. Use raw string literals here.
static constexpr FormatterTestCase k100ColTestCases[] = {
{
R"sv(
module m;
localparam int DDDDDDDDDDD = pppppppppppppppppp + LLLLLLLLLLLLLL
+ ((EEEEEEEEEEEE && FFFFFFFFFFFFFF > 0) ? hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh : 0);
endmodule
)sv",
// make sure the '+' after 'pppppppppppppppppp' is on the same line
R"sv(
module m;
localparam int DDDDDDDDDDD = pppppppppppppppppp +
LLLLLLLLLLLLLL + ((EEEEEEEEEEEE && FFFFFFFFFFFFFF > 0) ? hhhhhhhhhhhhhhhhhhhhhhhhhhhhhh : 0);
endmodule
)sv"},
{
R"sv(
module m;
assign bbbbbbbbbbbbbbbbb =
iiiiiiiiiiiiiiiiiiiii ?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx :
yyyyyyyyyyyyyyyyyyyyyy;
endmodule
)sv",
// make sure break happens after '?' and ':'
R"sv(
module m;
assign bbbbbbbbbbbbbbbbb = iiiiiiiiiiiiiiiiiiiii ?
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx : yyyyyyyyyyyyyyyyyyyyyy;
endmodule
)sv"},
{
R"sv(
module m;
if (x) begin
assign {ooooooooooooooooooo, ssssssssss} =
bbbbbbbbbbbbbbbbb >= cccccccccccccccccccccccc
? ddddd - (qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq) :
eeeee - (rrrrrrrrrrrrrrrrrrfffjjjjjjjjjjjjjjjjjgggkkkkkkkkkkkkkkkkkkkkkkkk);
end
endmodule
)sv",
// make sure break happens after '?' and ':'
R"sv(
module m;
if (x) begin
assign {ooooooooooooooooooo, ssssssssss} = bbbbbbbbbbbbbbbbb >= cccccccccccccccccccccccc ?
ddddd - (qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq) :
eeeee - (rrrrrrrrrrrrrrrrrrfffjjjjjjjjjjjjjjjjjgggkkkkkkkkkkkkkkkkkkkkkkkk);
end
endmodule
)sv"},
};
TEST(FormatterEndToEndTest, PenaltySensitiveLineWrapping100Col) {
FormatStyle style;
style.column_limit = 100;
style.indentation_spaces = 2;
style.wrap_spaces = 4;
for (const auto& test_case : k100ColTestCases) {
VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
std::ostringstream stream, debug_stream;
ExecutionControl control;
control.stream = &debug_stream;
const auto status = FormatVerilog(test_case.input, "<filename>", style,
stream, kEnableAllLines, control);
EXPECT_OK(status);
EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
EXPECT_TRUE(debug_stream.str().empty());
}
}
} // namespace
} // namespace formatter
} // namespace verilog