fix build under newer KConfig by bump cmake min version

This commit is contained in:
2024-09-04 19:01:58 +08:00
parent 727a2ec214
commit 9fb3681e3a
1022 changed files with 4414 additions and 1375 deletions

View File

@ -0,0 +1,23 @@
Boost Software License - Version 1.0 - August 17th, 2003
Permission is hereby granted, free of charge, to any person or organization
obtaining a copy of the software and accompanying documentation covered by
this license (the "Software") to use, reproduce, display, distribute,
execute, and transmit the Software, and to prepare derivative works of the
Software, and to permit third-parties to whom the Software is furnished to
do so, all subject to the following:
The copyright notices in the Software and this entire statement, including
the above license grant, this restriction and the following disclaimer,
must be included in all copies of the Software, in whole or in part, and
all derivative works of the Software, unless such copies or derivative
works are solely in the form of machine-executable object code generated by
a source language processor.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,15 @@
The test/unit directory contains unit tests for Scintilla data structures.
The tests can be run on Windows, macOS, or Linux using g++ and GNU make.
The Catch test framework is used.
https://github.com/philsquared/Catch
The file catch.hpp is under the Boost Software License which is contained in LICENSE_1_0.txt
To run the tests on macOS or Linux:
make test
To run the tests on Windows:
mingw32-make test
Visual C++ (2010+) and nmake can also be used on Windows:
nmake -f test.mak test

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
<Type Name="Scintilla::SplitVector&lt;*&gt;">
<DisplayString>{{size = {lengthBody}}}</DisplayString>
<Expand>
<Item Name="[size]">lengthBody</Item>
<Item Name="[part1Length]">part1Length</Item>
<Item Name="[gap]">gapLength</Item>
<IndexListItems>
<Size>lengthBody</Size>
<ValueNode>body[($i&lt;part1Length)?$i:$i+gapLength]</ValueNode>
</IndexListItems>
</Expand>
</Type>
<Type Name="Scintilla::Partitioning&lt;*&gt;">
<DisplayString>{{size = {body->lengthBody}}}</DisplayString>
<Expand>
<IndexListItems>
<Size>body->lengthBody</Size>
<ValueNode>body->body[($i&lt;body->part1Length)?$i:$i+body->gapLength]+($i&gt;stepPartition?stepLength:0)</ValueNode>
</IndexListItems>
</Expand>
</Type>
<Type Name="std::unique_ptr&lt;*&gt;">
<SmartPointer Usage="Minimal">_Mypair._Myval2</SmartPointer>
<DisplayString Condition="_Mypair._Myval2 == 0">empty</DisplayString>
<DisplayString Condition="_Mypair._Myval2 != 0">unique_ptr {*_Mypair._Myval2}</DisplayString>
<Expand>
<ExpandedItem Condition="_Mypair._Myval2 != 0">_Mypair._Myval2</ExpandedItem>
<ExpandedItem Condition="_Mypair._Myval2 != 0">_Mypair</ExpandedItem>
</Expand>
</Type>
</AutoVisualizer>

View File

@ -0,0 +1,5 @@
command.go.*.cxx=./unitTest
if PLAT_WIN
make.command=mingw32-make
command.go.*.cxx=unitTest
command.go.needs.$(file.patterns.cplusplus)=$(make.command)

View File

@ -0,0 +1,24 @@
/** @file UnitTester.cxx
** UnitTester.cpp : Defines the entry point for the console application.
**/
// Catch uses std::uncaught_exception which is deprecated in C++17.
// This define silences a warning from Visual C++.
#define _SILENCE_CXX17_UNCAUGHT_EXCEPTION_DEPRECATION_WARNING
#include <cstdio>
#include <cstdarg>
#include <string_view>
#include <vector>
#include <memory>
#define CATCH_CONFIG_WINDOWS_CRTDBG
#define CATCH_CONFIG_RUNNER
#include "catch.hpp"
int main(int argc, char* argv[]) {
const int result = Catch::Session().run(argc, argv);
return result;
}

View File

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{35688A27-D91B-453A-8A05-65A7F28DEFBF}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>UnitTester</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;CHECK_CORRECTNESS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\include\;..\..\lexlib\;..\..\..\scintilla\include\</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;CHECK_CORRECTNESS;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\include\;..\..\lexlib\;..\..\..\scintilla\include\</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;CHECK_CORRECTNESS;WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\include\;..\..\lexlib\;..\..\..\scintilla\include\</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS=1;_HAS_AUTO_PTR_ETC=1;_SCL_SECURE_NO_WARNINGS=1;CHECK_CORRECTNESS;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<AdditionalIncludeDirectories>..\..\include\;..\..\lexlib\;..\..\..\scintilla\include\</AdditionalIncludeDirectories>
<LanguageStandard>stdcpp17</LanguageStandard>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="..\..\lexlib\Accessor.cxx" />
<ClCompile Include="..\..\lexlib\CharacterSet.cxx" />
<ClCompile Include="..\..\lexlib\InList.cxx" />
<ClCompile Include="..\..\lexlib\LexerBase.cxx" />
<ClCompile Include="..\..\lexlib\LexerModule.cxx" />
<ClCompile Include="..\..\lexlib\LexerSimple.cxx" />
<ClCompile Include="..\..\lexlib\PropSetSimple.cxx" />
<ClCompile Include="..\..\lexlib\WordList.cxx" />
<ClCompile Include="test*.cxx" />
<ClCompile Include="UnitTester.cxx" />
</ItemGroup>
<ItemGroup>
<Natvis Include="Sci.natvis" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
# Build all the unit tests using GNU make and either g++ or clang
# Should be run using mingw32-make on Windows, not nmake
# On Windows g++ is used, on macOS clang, and on Linux G++ is used by default
# but clang can be used by defining CLANG when invoking make
# clang works only with libc++, not libstdc++
# Tested with clang 9 and g++ 9
CXXSTD=c++17
ifndef windir
ifeq ($(shell uname),Darwin)
# On macOS always use clang as g++ is old version
CLANG = 1
USELIBCPP = 1
endif
endif
CXXFLAGS += --std=$(CXXSTD)
ifdef CLANG
CXX = clang++
ifdef USELIBCPP
# macOS, use libc++ but don't have sanitizers
CXXFLAGS += --stdlib=libc++
else
# Linux, have sanitizers
SANITIZE = -fsanitize=address,undefined
CXXFLAGS += $(SANITIZE)
endif
else
CXX = g++
endif
ifdef windir
DEL = del /q
EXE = unitTest.exe
else
DEL = rm -f
EXE = unitTest
endif
vpath %.cxx ../../lexlib
INCLUDEDIRS = -I ../../include -I../../lexlib -I../../../scintilla/include
CPPFLAGS += $(INCLUDEDIRS)
CXXFLAGS += -Wall -Wextra
# Files in this directory containing tests
TESTSRC=$(wildcard test*.cxx)
TESTOBJ=$(TESTSRC:.cxx=.o)
# Files being tested from lexilla/lexlib directory
TESTEDOBJ=\
Accessor.o \
CharacterSet.o \
InList.o \
LexerBase.o \
LexerModule.o \
LexerSimple.o \
PropSetSimple.o \
WordList.o
TESTS=$(EXE)
all: $(TESTS)
test: $(TESTS)
./$(EXE)
clean:
$(DEL) $(TESTS) *.o *.obj *.exe
%.o: %.cxx
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -c $< -o $@
$(EXE): unitTest.o $(TESTOBJ) $(TESTEDOBJ)
$(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LINKFLAGS) $^ -o $@

View File

@ -0,0 +1,35 @@
# Build all the unit tests with Microsoft Visual C++ using nmake
# Tested with Visual C++ 2022
DEL = del /q
EXE = unitTest.exe
INCLUDEDIRS = /I../../include /I../../lexlib /I../../../scintilla/include
CXXFLAGS = /MP /EHsc /std:c++17 /D_HAS_AUTO_PTR_ETC=1 /wd 4805 $(INCLUDEDIRS)
# Files in this directory containing tests
TESTSRC=test*.cxx
# Files being tested from lexilla/lexlib directory
TESTEDSRC=\
../../lexlib/Accessor.cxx \
../../lexlib/CharacterSet.cxx \
../../lexlib/InList.cxx \
../../lexlib/LexerBase.cxx \
../../lexlib/LexerModule.cxx \
../../lexlib/LexerSimple.cxx \
../../lexlib/PropSetSimple.cxx \
../../lexlib/WordList.cxx
TESTS=$(EXE)
all: $(TESTS)
test: $(TESTS)
$(EXE)
clean:
$(DEL) $(TESTS) *.o *.obj *.exe
$(EXE): $(TESTSRC) $(TESTEDSRC) $(@B).cxx
$(CXX) $(CXXFLAGS) /Fe$@ $**

View File

@ -0,0 +1,151 @@
/** @file testCharacterSet.cxx
** Unit Tests for Lexilla internal data structures
**/
#include <cstdlib>
#include <cassert>
#include <string_view>
#include "CharacterSet.h"
#include "catch.hpp"
using namespace Lexilla;
// Test CharacterSet.
TEST_CASE("CharacterSet") {
SECTION("IsEmptyInitially") {
CharacterSet cs;
for (int i=0; i<0x80; i++) {
REQUIRE(!cs.Contains(i));
}
}
SECTION("InitialSet") {
CharacterSet cs(CharacterSet::setDigits);
for (int i=0; i<0x80; i++) {
if (i >= '0' && i <= '9')
REQUIRE(cs.Contains(i));
else
REQUIRE(!cs.Contains(i));
}
}
SECTION("Set") {
CharacterSet cs;
cs.Add('a');
for (int i=0; i<0x80; i++) {
if (i == 'a')
REQUIRE(cs.Contains(i));
else
REQUIRE(!cs.Contains(i));
}
}
SECTION("After") {
CharacterSet cs;
REQUIRE(!cs.Contains(0x100));
CharacterSet cs2(CharacterSet::setNone, "", 0x80, true);
REQUIRE(cs2.Contains(0x100));
}
}
TEST_CASE("Functions") {
SECTION("IsASpace") {
REQUIRE(IsASpace(' '));
REQUIRE(!IsASpace('a'));
REQUIRE(IsASpaceOrTab(' '));
REQUIRE(!IsASpaceOrTab('a'));
}
SECTION("IsADigit") {
REQUIRE(!IsADigit(' '));
REQUIRE(!IsADigit('a'));
REQUIRE(IsADigit('7'));
REQUIRE(IsADigit('7', 16));
REQUIRE(IsADigit('A', 16));
REQUIRE(IsADigit('a', 16));
REQUIRE(!IsADigit('8', 8));
}
SECTION("IsASCII") {
REQUIRE(IsASCII(' '));
REQUIRE(IsASCII('a'));
REQUIRE(!IsASCII(-1));
REQUIRE(!IsASCII(128));
}
SECTION("IsUpperOrLowerCase") {
REQUIRE(IsLowerCase('a'));
REQUIRE(!IsLowerCase('A'));
REQUIRE(!IsUpperCase('a'));
REQUIRE(IsUpperCase('A'));
REQUIRE(IsUpperOrLowerCase('a'));
REQUIRE(IsUpperOrLowerCase('A'));
REQUIRE(!IsUpperOrLowerCase('9'));
REQUIRE(IsAlphaNumeric('9'));
REQUIRE(IsAlphaNumeric('a'));
REQUIRE(IsAlphaNumeric('A'));
REQUIRE(!IsAlphaNumeric(' '));
REQUIRE(!IsAlphaNumeric('+'));
}
SECTION("isoperator") {
REQUIRE(isspacechar(' '));
REQUIRE(!isspacechar('a'));
REQUIRE(!iswordchar(' '));
REQUIRE(iswordchar('a'));
REQUIRE(iswordchar('A'));
REQUIRE(iswordchar('.'));
REQUIRE(iswordchar('_'));
REQUIRE(!iswordstart(' '));
REQUIRE(iswordstart('a'));
REQUIRE(iswordstart('A'));
REQUIRE(iswordstart('_'));
REQUIRE(!isoperator('a'));
REQUIRE(isoperator('+'));
}
SECTION("MakeUpperCase") {
REQUIRE(MakeUpperCase(' ') == ' ');
REQUIRE(MakeUpperCase('A') == 'A');
REQUIRE(MakeUpperCase('a') == 'A');
REQUIRE(MakeLowerCase(' ') == ' ');
REQUIRE(MakeLowerCase('A') == 'a');
REQUIRE(MakeLowerCase('a') == 'a');
}
SECTION("CompareCaseInsensitive") {
REQUIRE(CompareCaseInsensitive(" ", " ") == 0);
REQUIRE(CompareCaseInsensitive("A", "A") == 0);
REQUIRE(CompareCaseInsensitive("a", "A") == 0);
REQUIRE(CompareCaseInsensitive("b", "A") != 0);
REQUIRE(CompareCaseInsensitive("aa", "A") != 0);
REQUIRE(CompareNCaseInsensitive(" ", " ", 1) == 0);
REQUIRE(CompareNCaseInsensitive("b", "A", 1) != 0);
REQUIRE(CompareNCaseInsensitive("aa", "A", 1) == 0);
}
SECTION("EqualCaseInsensitive") {
REQUIRE(EqualCaseInsensitive(" ", " "));
REQUIRE(EqualCaseInsensitive("A", "A"));
REQUIRE(EqualCaseInsensitive("a", "A"));
REQUIRE(!EqualCaseInsensitive("b", "A"));
REQUIRE(!EqualCaseInsensitive("aa", "A"));
REQUIRE(!EqualCaseInsensitive("a", "AA"));
}
}

View File

@ -0,0 +1,28 @@
/** @file testInList.cxx
** Unit Tests for Lexilla internal data structures
**/
#include <cstdlib>
#include <cassert>
#include <string_view>
#include <initializer_list>
#include "InList.h"
#include "catch.hpp"
using namespace Lexilla;
// Test InList.
TEST_CASE("InList") {
SECTION("Basic") {
REQUIRE(InList("dog", {"cat", "dog", "frog"}));
REQUIRE(!InList("fly", {"cat", "dog", "frog"}));
REQUIRE(InListCaseInsensitive("DOG", {"cat", "dog", "frog"}));
REQUIRE(!InListCaseInsensitive("fly", {"cat", "dog", "frog"}));
}
}

View File

@ -0,0 +1,66 @@
/** @file testLexerSimple.cxx
** Unit Tests for Lexilla internal data structures
**/
#include <cassert>
#include <string>
#include <string_view>
#include "ILexer.h"
#include "Scintilla.h"
#include "PropSetSimple.h"
#include "LexerModule.h"
#include "LexerBase.h"
#include "LexerSimple.h"
#include "catch.hpp"
using namespace Lexilla;
// Test LexerSimple.
namespace {
constexpr const char *propertyName = "lexer.tex.comment.process";
constexpr const char *propertyValue = "1";
void ColouriseDocument(Sci_PositionU, Sci_Position, int, WordList *[], Accessor &) {
// Do no styling
}
LexerModule lmSimpleExample(123456, ColouriseDocument, "simpleexample");
}
TEST_CASE("LexerSimple") {
SECTION("Identifier") {
LexerSimple lexSimple(&lmSimpleExample);
REQUIRE(lexSimple.GetIdentifier() == 123456);
}
SECTION("Identifier") {
LexerSimple lexSimple(&lmSimpleExample);
REQUIRE_THAT(lexSimple.GetName(), Catch::Matchers::Equals("simpleexample"));
}
SECTION("SetAndGet") {
LexerSimple lexSimple(&lmSimpleExample);
// New setting -> 0
const Sci_Position pos0 = lexSimple.PropertySet(propertyName, "8");
REQUIRE(pos0 == 0);
// Changed setting -> 0
const Sci_Position pos1 = lexSimple.PropertySet(propertyName, propertyValue);
REQUIRE(pos1 == 0);
// Same setting -> -1
const Sci_Position pos2 = lexSimple.PropertySet(propertyName, propertyValue);
REQUIRE(pos2 == -1);
const char *value = lexSimple.PropertyGet(propertyName);
REQUIRE_THAT(propertyValue, Catch::Matchers::Equals(value));
}
}

View File

@ -0,0 +1,126 @@
/** @file testOptionSet.cxx
** Unit Tests for Lexilla internal data structures
** Tests OptionSet.
**/
#include <string>
#include <string_view>
#include <vector>
#include <map>
#include "Scintilla.h"
#include "OptionSet.h"
#include "catch.hpp"
using namespace Lexilla;
// Test OptionSet.
namespace {
// Simple example options structure with each type: string, bool, int
struct Options {
std::string so;
bool bo = false;
int io = 0;
};
const char *const denseWordLists[] = {
"Keywords 1",
"Keywords 2",
"Keywords 3",
"Keywords 4",
nullptr,
};
const char *const sparseWordLists[] = {
"",
"",
"Keywords 1",
"",
"Keywords 2",
nullptr,
};
}
using Catch::Matchers::Equals;
TEST_CASE("OptionSet") {
OptionSet<Options> os;
Options options;
SECTION("IsEmptyInitially") {
REQUIRE_THAT(os.PropertyNames(), Equals(""));
}
SECTION("MissingOption") {
// Check for not present option
REQUIRE_FALSE(os.PropertyGet("missing"));
REQUIRE(SC_TYPE_BOOLEAN == os.PropertyType("missing"));
REQUIRE_FALSE(os.PropertySet(&options, "missing", "1"));
}
SECTION("Define") {
os.DefineProperty("string.option", &Options::so, "StringOption");
REQUIRE_THAT(os.PropertyGet("string.option"), Equals(""));
REQUIRE(SC_TYPE_STRING == os.PropertyType("string.option"));
REQUIRE_THAT(os.DescribeProperty("string.option"), Equals("StringOption"));
os.DefineProperty("bool.option", &Options::bo, "BoolOption");
REQUIRE_THAT(os.PropertyGet("bool.option"), Equals(""));
REQUIRE(SC_TYPE_BOOLEAN == os.PropertyType("bool.option"));
REQUIRE_THAT(os.DescribeProperty("bool.option"), Equals("BoolOption"));
os.DefineProperty("int.option", &Options::io, "IntOption");
REQUIRE_THAT(os.PropertyGet("int.option"), Equals(""));
REQUIRE(SC_TYPE_INTEGER == os.PropertyType("int.option"));
REQUIRE_THAT(os.DescribeProperty("int.option"), Equals("IntOption"));
// This is really a set and could be reordered but is currently in definition order
REQUIRE_THAT(os.PropertyNames(), Equals("string.option\nbool.option\nint.option"));
}
SECTION("Set") {
os.DefineProperty("string.option", &Options::so, "StringOption");
REQUIRE_THAT(os.PropertyGet("string.option"), Equals(""));
REQUIRE(os.PropertySet(&options, "string.option", "string"));
REQUIRE_THAT(os.PropertyGet("string.option"), Equals("string"));
// Setting to same as before returns false
REQUIRE_FALSE(os.PropertySet(&options, "string.option", "string"));
REQUIRE(os.PropertySet(&options, "string.option", "anotherString"));
REQUIRE_THAT(os.PropertyGet("string.option"), Equals("anotherString"));
os.DefineProperty("bool.option", &Options::so, "BoolOption");
REQUIRE(os.PropertySet(&options, "bool.option", "1"));
REQUIRE_THAT(os.PropertyGet("bool.option"), Equals("1"));
// Setting to same as before returns false
REQUIRE_FALSE(os.PropertySet(&options, "bool.option", "1"));
REQUIRE(os.PropertySet(&options, "bool.option", "0"));
os.DefineProperty("int.option", &Options::so, "IntOption");
REQUIRE(os.PropertySet(&options, "int.option", "2"));
REQUIRE_THAT(os.PropertyGet("int.option"), Equals("2"));
// Setting to same as before returns false
REQUIRE_FALSE(os.PropertySet(&options, "int.option", "2"));
REQUIRE(os.PropertySet(&options, "int.option", "3"));
}
// WordListSets feature is really completely separate from options
SECTION("WordListSets") {
REQUIRE_THAT(os.DescribeWordListSets(), Equals(""));
os.DefineWordListSets(denseWordLists);
REQUIRE_THAT(os.DescribeWordListSets(),
Equals("Keywords 1\nKeywords 2\nKeywords 3\nKeywords 4"));
OptionSet<Options> os2;
REQUIRE_THAT(os2.DescribeWordListSets(), Equals(""));
os2.DefineWordListSets(sparseWordLists);
REQUIRE_THAT(os2.DescribeWordListSets(),
Equals("\n\nKeywords 1\n\nKeywords 2"));
}
}

View File

@ -0,0 +1,49 @@
/** @file testPropSetSimple.cxx
** Unit Tests for Lexilla internal data structures
**/
#include <string>
#include <string_view>
#include "PropSetSimple.h"
#include "catch.hpp"
using namespace Lexilla;
// Test PropSetSimple.
namespace {
constexpr const char *propertyName = "lexer.tex.comment.process";
constexpr const char *propertyValue = "1";
}
TEST_CASE("PropSetSimple") {
SECTION("IsEmptyInitially") {
PropSetSimple pss;
const char *value = pss.Get(propertyName);
REQUIRE_THAT(value, Catch::Matchers::Equals(""));
}
SECTION("SetAndGet") {
PropSetSimple pss;
pss.Set(propertyName, propertyValue);
const char *value = pss.Get(propertyName);
REQUIRE_THAT(value, Catch::Matchers::Equals(propertyValue));
}
SECTION("GetInt") {
PropSetSimple pss;
const int valueStart = pss.GetInt(propertyName);
REQUIRE(0 == valueStart);
const int valueDefault = pss.GetInt(propertyName, 3);
REQUIRE(3 == valueDefault);
pss.Set(propertyName, propertyValue);
const int value = pss.GetInt(propertyName);
REQUIRE(1 == value);
}
}

View File

@ -0,0 +1,234 @@
/** @file testSparseState.cxx
** Unit Tests for Lexilla internal data structures
**/
#include <string>
#include <string_view>
#include <vector>
#include <algorithm>
#include <memory>
#include "Sci_Position.h"
#include "SparseState.h"
#include "catch.hpp"
using namespace Lexilla;
// Test SparseState.
TEST_CASE("SparseState") {
SparseState<int> ss;
SECTION("IsEmptyInitially") {
REQUIRE(0u == ss.size());
int val = ss.ValueAt(0);
REQUIRE(0 == val);
}
SECTION("SimpleSetAndGet") {
ss.Set(0, 22);
ss.Set(1, 23);
REQUIRE(2u == ss.size());
REQUIRE(0 == ss.ValueAt(-1));
REQUIRE(22 == ss.ValueAt(0));
REQUIRE(23 == ss.ValueAt(1));
REQUIRE(23 == ss.ValueAt(2));
}
SECTION("RetrieveBetween") {
ss.Set(0, 10);
ss.Set(2, 12);
REQUIRE(2u == ss.size());
REQUIRE(0 == ss.ValueAt(-1));
REQUIRE(10 == ss.ValueAt(0));
REQUIRE(10 == ss.ValueAt(1));
REQUIRE(12 == ss.ValueAt(2));
}
SECTION("RetrieveBefore") {
ss.Set(2, 12);
REQUIRE(1u == ss.size());
REQUIRE(0 == ss.ValueAt(-1));
REQUIRE(0 == ss.ValueAt(0));
REQUIRE(0 == ss.ValueAt(1));
REQUIRE(12 == ss.ValueAt(2));
}
SECTION("Delete") {
ss.Set(0, 30);
ss.Set(2, 32);
ss.Delete(2);
REQUIRE(1u == ss.size());
REQUIRE(0 == ss.ValueAt(-1));
REQUIRE(30 == ss.ValueAt(0));
REQUIRE(30 == ss.ValueAt(1));
REQUIRE(30 == ss.ValueAt(2));
}
SECTION("DeleteBetween") {
ss.Set(0, 30);
ss.Set(2, 32);
ss.Delete(1);
REQUIRE(1u == ss.size());
REQUIRE(0 == ss.ValueAt(-1));
REQUIRE(30 == ss.ValueAt(0));
REQUIRE(30 == ss.ValueAt(1));
REQUIRE(30 == ss.ValueAt(2));
}
SECTION("ReplaceLast") {
ss.Set(0, 30);
ss.Set(2, 31);
ss.Set(2, 32);
REQUIRE(2u == ss.size());
REQUIRE(0 == ss.ValueAt(-1));
REQUIRE(30 == ss.ValueAt(0));
REQUIRE(30 == ss.ValueAt(1));
REQUIRE(32 == ss.ValueAt(2));
REQUIRE(32 == ss.ValueAt(3));
}
SECTION("OnlyChangeAppended") {
ss.Set(0, 30);
ss.Set(2, 31);
ss.Set(3, 31);
REQUIRE(2u == ss.size());
}
SECTION("MergeBetween") {
ss.Set(0, 30);
ss.Set(2, 32);
ss.Set(4, 34);
REQUIRE(3u == ss.size());
SparseState<int> ssAdditions(3);
ssAdditions.Set(4, 34);
REQUIRE(1u == ssAdditions.size());
bool mergeChanged = ss.Merge(ssAdditions,5);
REQUIRE(false == mergeChanged);
ssAdditions.Set(4, 44);
REQUIRE(1u == ssAdditions.size());
mergeChanged = ss.Merge(ssAdditions,5);
REQUIRE(true == mergeChanged);
REQUIRE(3u == ss.size());
REQUIRE(44 == ss.ValueAt(4));
}
SECTION("MergeAtExisting") {
ss.Set(0, 30);
ss.Set(2, 32);
ss.Set(4, 34);
REQUIRE(3u == ss.size());
SparseState<int> ssAdditions(4);
ssAdditions.Set(4, 34);
REQUIRE(1u == ssAdditions.size());
bool mergeChanged = ss.Merge(ssAdditions,5);
REQUIRE(false == mergeChanged);
ssAdditions.Set(4, 44);
REQUIRE(1u == ssAdditions.size());
mergeChanged = ss.Merge(ssAdditions,5);
REQUIRE(true == mergeChanged);
REQUIRE(3u == ss.size());
REQUIRE(44 == ss.ValueAt(4));
}
SECTION("MergeWhichRemoves") {
ss.Set(0, 30);
ss.Set(2, 32);
ss.Set(4, 34);
REQUIRE(3u == ss.size());
SparseState<int> ssAdditions(2);
ssAdditions.Set(2, 22);
REQUIRE(1u == ssAdditions.size());
REQUIRE(22 == ssAdditions.ValueAt(2));
bool mergeChanged = ss.Merge(ssAdditions,5);
REQUIRE(true == mergeChanged);
REQUIRE(2u == ss.size());
REQUIRE(22 == ss.ValueAt(2));
}
SECTION("MergeIgnoreSome") {
ss.Set(0, 30);
ss.Set(2, 32);
ss.Set(4, 34);
SparseState<int> ssAdditions(2);
ssAdditions.Set(2, 32);
bool mergeChanged = ss.Merge(ssAdditions,3);
REQUIRE(false == mergeChanged);
REQUIRE(2u == ss.size());
REQUIRE(32 == ss.ValueAt(2));
}
SECTION("MergeIgnoreSomeStart") {
ss.Set(0, 30);
ss.Set(2, 32);
ss.Set(4, 34);
SparseState<int> ssAdditions(2);
ssAdditions.Set(2, 32);
bool mergeChanged = ss.Merge(ssAdditions,2);
REQUIRE(false == mergeChanged);
REQUIRE(2u == ss.size());
REQUIRE(32 == ss.ValueAt(2));
}
SECTION("MergeIgnoreRepeat") {
ss.Set(0, 30);
ss.Set(2, 32);
ss.Set(4, 34);
SparseState<int> ssAdditions(5);
// Appending same value as at end of pss.
ssAdditions.Set(5, 34);
bool mergeChanged = ss.Merge(ssAdditions,6);
REQUIRE(false == mergeChanged);
REQUIRE(3u == ss.size());
REQUIRE(34 == ss.ValueAt(4));
}
}
TEST_CASE("SparseStateString") {
SparseState<std::string> ss;
SECTION("IsEmptyInitially") {
REQUIRE(0u == ss.size());
std::string val = ss.ValueAt(0);
REQUIRE("" == val);
}
SECTION("SimpleSetAndGet") {
REQUIRE(0u == ss.size());
ss.Set(0, "22");
ss.Set(1, "23");
REQUIRE(2u == ss.size());
REQUIRE("" == ss.ValueAt(-1));
REQUIRE("22" == ss.ValueAt(0));
REQUIRE("23" == ss.ValueAt(1));
REQUIRE("23" == ss.ValueAt(2));
}
SECTION("DeleteBetween") {
ss.Set(0, "30");
ss.Set(2, "32");
ss.Delete(1);
REQUIRE(1u == ss.size());
REQUIRE("" == ss.ValueAt(-1));
REQUIRE("30" == ss.ValueAt(0));
REQUIRE("30" == ss.ValueAt(1));
REQUIRE("30" == ss.ValueAt(2));
}
}

View File

@ -0,0 +1,212 @@
/** @file testWordList.cxx
** Unit Tests for Lexilla internal data structures
** Tests WordList, WordClassifier, and SubStyles
**/
#include <cassert>
#include <string>
#include <string_view>
#include <vector>
#include <map>
#include "WordList.h"
#include "CharacterSet.h"
#include "SubStyles.h"
#include "catch.hpp"
using namespace Lexilla;
// Test WordList.
TEST_CASE("WordList") {
WordList wl;
SECTION("IsEmptyInitially") {
REQUIRE(0 == wl.Length());
REQUIRE(!wl.InList("struct"));
}
SECTION("InList") {
wl.Set("else struct");
REQUIRE(2 == wl.Length());
REQUIRE(wl.InList("struct"));
REQUIRE(!wl.InList("class"));
}
SECTION("StringInList") {
wl.Set("else struct");
std::string sStruct = "struct";
REQUIRE(wl.InList(sStruct));
std::string sClass = "class";
REQUIRE(!wl.InList(sClass));
}
SECTION("InListUnicode") {
// "cheese" in English
// "kase" ('k', 'a with diaeresis', 's', 'e') in German
// "syr", ('CYRILLIC SMALL LETTER ES', 'CYRILLIC SMALL LETTER YERU', 'CYRILLIC SMALL LETTER ER') in Russian
wl.Set("cheese \x6b\xc3\xa4\x73\x65 \xd1\x81\xd1\x8b\xd1\x80");
REQUIRE(3 == wl.Length());
REQUIRE(wl.InList("cheese"));
REQUIRE(wl.InList("\x6b\xc3\xa4\x73\x65"));
REQUIRE(wl.InList("\xd1\x81\xd1\x8b\xd1\x80"));
}
SECTION("Set") {
// Check whether Set returns whether it has changed correctly
const bool changed = wl.Set("else struct");
REQUIRE(changed);
// Changing to same thing
const bool changed2 = wl.Set("else struct");
REQUIRE(!changed2);
// Changed order shouldn't be seen as a change
const bool changed3 = wl.Set("struct else");
REQUIRE(!changed3);
// Removing word is a change
const bool changed4 = wl.Set("struct");
REQUIRE(changed4);
}
SECTION("WordAt") {
wl.Set("else struct");
REQUIRE_THAT(wl.WordAt(0), Catch::Matchers::Equals("else"));
}
SECTION("InListAbbreviated") {
wl.Set("else stru~ct w~hile \xd1\x81~\xd1\x8b\xd1\x80");
REQUIRE(wl.InListAbbreviated("else", '~'));
REQUIRE(wl.InListAbbreviated("struct", '~'));
REQUIRE(wl.InListAbbreviated("stru", '~'));
REQUIRE(wl.InListAbbreviated("struc", '~'));
REQUIRE(!wl.InListAbbreviated("str", '~'));
REQUIRE(wl.InListAbbreviated("while", '~'));
REQUIRE(wl.InListAbbreviated("wh", '~'));
// TODO: Next line fails but should allow single character prefixes
//REQUIRE(wl.InListAbbreviated("w", '~'));
REQUIRE(!wl.InListAbbreviated("", '~'));
// Russian syr
REQUIRE(wl.InListAbbreviated("\xd1\x81\xd1\x8b\xd1\x80", '~'));
}
SECTION("InListAbridged") {
wl.Set("list w.~.active bo~k a~z ~_frozen \xd1\x81~\xd1\x80");
REQUIRE(wl.InListAbridged("list", '~'));
REQUIRE(wl.InListAbridged("w.front.active", '~'));
REQUIRE(wl.InListAbridged("w.x.active", '~'));
REQUIRE(wl.InListAbridged("w..active", '~'));
REQUIRE(!wl.InListAbridged("w.active", '~'));
REQUIRE(!wl.InListAbridged("w.x.closed", '~'));
REQUIRE(wl.InListAbridged("book", '~'));
REQUIRE(wl.InListAbridged("bok", '~'));
REQUIRE(!wl.InListAbridged("bk", '~'));
REQUIRE(wl.InListAbridged("a_frozen", '~'));
REQUIRE(wl.InListAbridged("_frozen", '~'));
REQUIRE(!wl.InListAbridged("frozen", '~'));
REQUIRE(wl.InListAbridged("abcz", '~'));
REQUIRE(wl.InListAbridged("abz", '~'));
REQUIRE(wl.InListAbridged("az", '~'));
// Russian syr
REQUIRE(wl.InListAbridged("\xd1\x81\xd1\x8b\xd1\x80", '~'));
}
}
// Test WordClassifier.
TEST_CASE("WordClassifier") {
constexpr int base = 1;
constexpr int key = 10;
constexpr int type = 11;
constexpr int other = 40;
WordClassifier wc(1);
SECTION("Base") {
REQUIRE(wc.Base() == base);
wc.Allocate(key, 2);
REQUIRE(wc.Start() == key);
REQUIRE(wc.Last() == type);
REQUIRE(wc.Length() == 2);
REQUIRE(wc.IncludesStyle(key));
REQUIRE(wc.IncludesStyle(type));
REQUIRE(!wc.IncludesStyle(other));
wc.Clear();
REQUIRE(wc.Base() == base);
REQUIRE(wc.Start() == 0);
REQUIRE(wc.Last() == -1);
REQUIRE(wc.Length() == 0);
}
SECTION("ValueFor") {
wc.Allocate(key, 2);
wc.SetIdentifiers(key, "else if then", false);
wc.SetIdentifiers(type, "double float int long", false);
REQUIRE(wc.ValueFor("if") == key);
REQUIRE(wc.ValueFor("double") == type);
REQUIRE(wc.ValueFor("fish") < 0);
wc.RemoveStyle(type);
REQUIRE(wc.ValueFor("double") < 0);
}
}
// Test SubStyles.
TEST_CASE("SubStyles") {
constexpr char bases[] = "\002\005";
constexpr int base = 2;
constexpr int base2 = 5;
constexpr int styleFirst = 0x80;
constexpr int stylesAvailable = 0x40;
constexpr int distanceToSecondary = 0x40;
SubStyles subStyles(bases, styleFirst, stylesAvailable, distanceToSecondary);
SECTION("All") {
REQUIRE(subStyles.DistanceToSecondaryStyles() == distanceToSecondary);
// Before allocation
REQUIRE(subStyles.Start(base) == 0);
const int startSubStyles = subStyles.Allocate(base, 3);
REQUIRE(startSubStyles == styleFirst);
REQUIRE(subStyles.Start(base) == styleFirst);
REQUIRE(subStyles.Length(base) == 3);
REQUIRE(subStyles.BaseStyle(128) == 2);
// Not a substyle so returns argument.
REQUIRE(subStyles.BaseStyle(96) == 96);
REQUIRE(subStyles.FirstAllocated() == styleFirst);
REQUIRE(subStyles.LastAllocated() == styleFirst + 3 - 1);
subStyles.SetIdentifiers(styleFirst, "int long size_t");
const WordClassifier &wc = subStyles.Classifier(base);
REQUIRE(wc.ValueFor("int") == styleFirst);
REQUIRE(wc.ValueFor("double") < 0);
// Add second set of substyles which shouldn't affect first
const int startSecondSet = subStyles.Allocate(base2, 2);
constexpr int expectedStylesSecond = styleFirst + 3;
REQUIRE(startSecondSet == expectedStylesSecond);
REQUIRE(subStyles.Start(base) == styleFirst);
REQUIRE(subStyles.Start(base2) == expectedStylesSecond);
REQUIRE(subStyles.LastAllocated() == styleFirst + 5 - 1);
// Clear and check that earlier call no longer works
subStyles.Free();
REQUIRE(subStyles.Start(base) == 0);
}
}

View File

@ -0,0 +1,29 @@
/** @file unitTest.cxx
** Unit Tests for Lexilla internal data structures
**/
/*
Currently tested:
WordList
SparseState
*/
#include <cstdio>
#include <cstdarg>
#include <string_view>
#include <vector>
#include <memory>
#if defined(__GNUC__)
// Want to avoid misleading indentation warnings in catch.hpp but the pragma
// may not be available so protect by turning off pragma warnings
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
#pragma GCC diagnostic ignored "-Wpragmas"
#if !defined(__clang__)
#pragma GCC diagnostic ignored "-Wmisleading-indentation"
#endif
#endif
#define CATCH_CONFIG_MAIN // This tells Catch to provide a main() - only do this in one cpp file
#include "catch.hpp"