mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
New classes UnitTest and UnitTestRunner. Minor updates to VST wrapper. Added a dynamic buffer for win32 midi input.
This commit is contained in:
parent
cac473bb1e
commit
d2b3c283eb
34 changed files with 1871 additions and 481 deletions
|
|
@ -342,6 +342,7 @@ OBJECTS := \
|
|||
$(OBJDIR)/juce_PropertiesFile_8faca026.o \
|
||||
$(OBJDIR)/juce_RecentlyOpenedFilesList_f791257.o \
|
||||
$(OBJDIR)/juce_UndoManager_33b197fc.o \
|
||||
$(OBJDIR)/juce_UnitTest_4a02c10d.o \
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
|
|
@ -1873,4 +1874,9 @@ $(OBJDIR)/juce_UndoManager_33b197fc.o: ../../src/utilities/juce_UndoManager.cpp
|
|||
@echo "Compiling juce_UndoManager.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
$(OBJDIR)/juce_UnitTest_4a02c10d.o: ../../src/utilities/juce_UnitTest.cpp
|
||||
-@mkdir -p $(OBJDIR)
|
||||
@echo "Compiling juce_UnitTest.cpp"
|
||||
@$(CXX) $(CXXFLAGS) -o "$@" -c "$<"
|
||||
|
||||
-include $(OBJECTS:%.o=%.d)
|
||||
|
|
|
|||
|
|
@ -337,6 +337,7 @@
|
|||
0DE731ED3EC994B9227C2741 = { isa = PBXBuildFile; fileRef = 4BE2727CCD2CD7603402C8FE; };
|
||||
A124FE5709D9324B5BAFFE53 = { isa = PBXBuildFile; fileRef = A618FC3255ECE14EC9259E6B; };
|
||||
A84A5CA4654AE87192A6A096 = { isa = PBXBuildFile; fileRef = A59A5DCFCCAAEA79D03C2B27; };
|
||||
55EDB4D9B702B469DB4655C3 = { isa = PBXBuildFile; fileRef = ADE5F12AA5AD969E2C7002B3; };
|
||||
389351359BA78C682E1931A6 = { isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjucedebug.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
144F56FCF3DF9EC922765901 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Application.cpp; path = ../../src/application/juce_Application.cpp; sourceTree = SOURCE_ROOT; };
|
||||
F6A490BA93AC3558E9A6FBB0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Application.h; path = ../../src/application/juce_Application.h; sourceTree = SOURCE_ROOT; };
|
||||
|
|
@ -1021,6 +1022,8 @@
|
|||
EECE464606AE845BFC4B941B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_UndoableAction.h; path = ../../src/utilities/juce_UndoableAction.h; sourceTree = SOURCE_ROOT; };
|
||||
A59A5DCFCCAAEA79D03C2B27 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_UndoManager.cpp; path = ../../src/utilities/juce_UndoManager.cpp; sourceTree = SOURCE_ROOT; };
|
||||
3C9E6597968358B57374502C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_UndoManager.h; path = ../../src/utilities/juce_UndoManager.h; sourceTree = SOURCE_ROOT; };
|
||||
ADE5F12AA5AD969E2C7002B3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_UnitTest.cpp; path = ../../src/utilities/juce_UnitTest.cpp; sourceTree = SOURCE_ROOT; };
|
||||
75700D13513346310CEAC30D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_UnitTest.h; path = ../../src/utilities/juce_UnitTest.h; sourceTree = SOURCE_ROOT; };
|
||||
2FD5C998952BE08F8ED3F262 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce.h; path = ../../juce.h; sourceTree = SOURCE_ROOT; };
|
||||
01778F26212AECCBF2452804 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Config.h; path = ../../juce_Config.h; sourceTree = SOURCE_ROOT; };
|
||||
D443FD24B52106986FC8A531 = { isa = PBXGroup; children = (
|
||||
|
|
@ -1803,7 +1806,9 @@
|
|||
FA833EFA9E93C7DBE6624676,
|
||||
EECE464606AE845BFC4B941B,
|
||||
A59A5DCFCCAAEA79D03C2B27,
|
||||
3C9E6597968358B57374502C ); name = utilities; sourceTree = "<group>"; };
|
||||
3C9E6597968358B57374502C,
|
||||
ADE5F12AA5AD969E2C7002B3,
|
||||
75700D13513346310CEAC30D ); name = utilities; sourceTree = "<group>"; };
|
||||
9AA3D660772E3D4C64EC7859 = { isa = PBXGroup; children = (
|
||||
D443FD24B52106986FC8A531,
|
||||
F2B0E44A08E127FD31184241,
|
||||
|
|
@ -2231,7 +2236,8 @@
|
|||
D8B9941A1375579D6CE7C1C4,
|
||||
0DE731ED3EC994B9227C2741,
|
||||
A124FE5709D9324B5BAFFE53,
|
||||
A84A5CA4654AE87192A6A096 ); runOnlyForDeploymentPostprocessing = 0; };
|
||||
A84A5CA4654AE87192A6A096,
|
||||
55EDB4D9B702B469DB4655C3 ); runOnlyForDeploymentPostprocessing = 0; };
|
||||
01555BA382FAED280FF5F58A = { isa = PBXNativeTarget; buildConfigurationList = D14EC3F0DC5861E37D35E15A; buildPhases = (
|
||||
8914D147048B9EE245989ACB ); buildRules = ( ); dependencies = ( ); name = Juce; productName = Juce; productReference = 389351359BA78C682E1931A6; productType = "com.apple.product-type.library.static"; };
|
||||
FCFFEDFC83101B196BFA2AE2 = { isa = PBXProject; buildConfigurationList = 3A1CB6B5ECF4A79CDE35CC66; compatibilityVersion = "Xcode 3.0"; hasScannedForEncodings = 0; mainGroup = 992526B83B6AA618A4FAECEB; projectDirPath = ""; projectRoot = ""; targets = ( 01555BA382FAED280FF5F58A ); };
|
||||
|
|
|
|||
|
|
@ -964,6 +964,8 @@
|
|||
<File RelativePath="..\..\src\utilities\juce_UndoableAction.h"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UndoManager.cpp"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UndoManager.h"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UnitTest.cpp"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UnitTest.h"/>
|
||||
</Filter>
|
||||
<File RelativePath="..\..\juce.h"/>
|
||||
<File RelativePath="..\..\juce_Config.h"/>
|
||||
|
|
|
|||
|
|
@ -964,6 +964,8 @@
|
|||
<File RelativePath="..\..\src\utilities\juce_UndoableAction.h"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UndoManager.cpp"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UndoManager.h"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UnitTest.cpp"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UnitTest.h"/>
|
||||
</Filter>
|
||||
<File RelativePath="..\..\juce.h"/>
|
||||
<File RelativePath="..\..\juce_Config.h"/>
|
||||
|
|
|
|||
|
|
@ -966,6 +966,8 @@
|
|||
<File RelativePath="..\..\src\utilities\juce_UndoableAction.h"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UndoManager.cpp"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UndoManager.h"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UnitTest.cpp"/>
|
||||
<File RelativePath="..\..\src\utilities\juce_UnitTest.h"/>
|
||||
</Filter>
|
||||
<File RelativePath="..\..\juce.h"/>
|
||||
<File RelativePath="..\..\juce_Config.h"/>
|
||||
|
|
|
|||
|
|
@ -425,6 +425,7 @@
|
|||
<ClCompile Include="..\..\src\utilities\juce_PropertiesFile.cpp"/>
|
||||
<ClCompile Include="..\..\src\utilities\juce_RecentlyOpenedFilesList.cpp"/>
|
||||
<ClCompile Include="..\..\src\utilities\juce_UndoManager.cpp"/>
|
||||
<ClCompile Include="..\..\src\utilities\juce_UnitTest.cpp"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\application\juce_Application.h"/>
|
||||
|
|
@ -768,6 +769,7 @@
|
|||
<ClInclude Include="..\..\src\utilities\juce_SystemClipboard.h"/>
|
||||
<ClInclude Include="..\..\src\utilities\juce_UndoableAction.h"/>
|
||||
<ClInclude Include="..\..\src\utilities\juce_UndoManager.h"/>
|
||||
<ClInclude Include="..\..\src\utilities\juce_UnitTest.h"/>
|
||||
<ClInclude Include="..\..\juce.h"/>
|
||||
<ClInclude Include="..\..\juce_Config.h"/>
|
||||
</ItemGroup>
|
||||
|
|
|
|||
|
|
@ -1201,6 +1201,9 @@
|
|||
<ClCompile Include="..\..\src\utilities\juce_UndoManager.cpp">
|
||||
<Filter>Juce\Source\utilities</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\src\utilities\juce_UnitTest.cpp">
|
||||
<Filter>Juce\Source\utilities</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\..\src\application\juce_Application.h">
|
||||
|
|
@ -2226,6 +2229,9 @@
|
|||
<ClInclude Include="..\..\src\utilities\juce_UndoManager.h">
|
||||
<Filter>Juce\Source\utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\src\utilities\juce_UnitTest.h">
|
||||
<Filter>Juce\Source\utilities</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\juce.h">
|
||||
<Filter>Juce\Source</Filter>
|
||||
</ClInclude>
|
||||
|
|
|
|||
|
|
@ -337,6 +337,7 @@
|
|||
0DE731ED3EC994B9227C2741 = { isa = PBXBuildFile; fileRef = 4BE2727CCD2CD7603402C8FE; };
|
||||
A124FE5709D9324B5BAFFE53 = { isa = PBXBuildFile; fileRef = A618FC3255ECE14EC9259E6B; };
|
||||
A84A5CA4654AE87192A6A096 = { isa = PBXBuildFile; fileRef = A59A5DCFCCAAEA79D03C2B27; };
|
||||
55EDB4D9B702B469DB4655C3 = { isa = PBXBuildFile; fileRef = ADE5F12AA5AD969E2C7002B3; };
|
||||
389351359BA78C682E1931A6 = { isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libjucedebug.a; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
144F56FCF3DF9EC922765901 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_Application.cpp; path = ../../src/application/juce_Application.cpp; sourceTree = SOURCE_ROOT; };
|
||||
F6A490BA93AC3558E9A6FBB0 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Application.h; path = ../../src/application/juce_Application.h; sourceTree = SOURCE_ROOT; };
|
||||
|
|
@ -1021,6 +1022,8 @@
|
|||
EECE464606AE845BFC4B941B = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_UndoableAction.h; path = ../../src/utilities/juce_UndoableAction.h; sourceTree = SOURCE_ROOT; };
|
||||
A59A5DCFCCAAEA79D03C2B27 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_UndoManager.cpp; path = ../../src/utilities/juce_UndoManager.cpp; sourceTree = SOURCE_ROOT; };
|
||||
3C9E6597968358B57374502C = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_UndoManager.h; path = ../../src/utilities/juce_UndoManager.h; sourceTree = SOURCE_ROOT; };
|
||||
ADE5F12AA5AD969E2C7002B3 = { isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = juce_UnitTest.cpp; path = ../../src/utilities/juce_UnitTest.cpp; sourceTree = SOURCE_ROOT; };
|
||||
75700D13513346310CEAC30D = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_UnitTest.h; path = ../../src/utilities/juce_UnitTest.h; sourceTree = SOURCE_ROOT; };
|
||||
2FD5C998952BE08F8ED3F262 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce.h; path = ../../juce.h; sourceTree = SOURCE_ROOT; };
|
||||
01778F26212AECCBF2452804 = { isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = juce_Config.h; path = ../../juce_Config.h; sourceTree = SOURCE_ROOT; };
|
||||
D443FD24B52106986FC8A531 = { isa = PBXGroup; children = (
|
||||
|
|
@ -1803,7 +1806,9 @@
|
|||
FA833EFA9E93C7DBE6624676,
|
||||
EECE464606AE845BFC4B941B,
|
||||
A59A5DCFCCAAEA79D03C2B27,
|
||||
3C9E6597968358B57374502C ); name = utilities; sourceTree = "<group>"; };
|
||||
3C9E6597968358B57374502C,
|
||||
ADE5F12AA5AD969E2C7002B3,
|
||||
75700D13513346310CEAC30D ); name = utilities; sourceTree = "<group>"; };
|
||||
9AA3D660772E3D4C64EC7859 = { isa = PBXGroup; children = (
|
||||
D443FD24B52106986FC8A531,
|
||||
F2B0E44A08E127FD31184241,
|
||||
|
|
@ -2231,7 +2236,8 @@
|
|||
D8B9941A1375579D6CE7C1C4,
|
||||
0DE731ED3EC994B9227C2741,
|
||||
A124FE5709D9324B5BAFFE53,
|
||||
A84A5CA4654AE87192A6A096 ); runOnlyForDeploymentPostprocessing = 0; };
|
||||
A84A5CA4654AE87192A6A096,
|
||||
55EDB4D9B702B469DB4655C3 ); runOnlyForDeploymentPostprocessing = 0; };
|
||||
01555BA382FAED280FF5F58A = { isa = PBXNativeTarget; buildConfigurationList = D14EC3F0DC5861E37D35E15A; buildPhases = (
|
||||
8914D147048B9EE245989ACB ); buildRules = ( ); dependencies = ( ); name = Juce; productName = Juce; productReference = 389351359BA78C682E1931A6; productType = "com.apple.product-type.library.static"; };
|
||||
FCFFEDFC83101B196BFA2AE2 = { isa = PBXProject; buildConfigurationList = 3A1CB6B5ECF4A79CDE35CC66; compatibilityVersion = "Xcode 3.0"; hasScannedForEncodings = 0; mainGroup = 992526B83B6AA618A4FAECEB; projectDirPath = ""; projectRoot = ""; targets = ( 01555BA382FAED280FF5F58A ); };
|
||||
|
|
|
|||
|
|
@ -1494,6 +1494,10 @@
|
|||
file="src/utilities/juce_UndoManager.cpp"/>
|
||||
<FILE id="ZMxSjySn" name="juce_UndoManager.h" compile="0" resource="0"
|
||||
file="src/utilities/juce_UndoManager.h"/>
|
||||
<FILE id="6QJ8o3k" name="juce_UnitTest.cpp" compile="1" resource="0"
|
||||
file="src/utilities/juce_UnitTest.cpp"/>
|
||||
<FILE id="PQBhHBA" name="juce_UnitTest.h" compile="0" resource="0"
|
||||
file="src/utilities/juce_UnitTest.h"/>
|
||||
</GROUP>
|
||||
<FILE id="Jp7xh1cg9" name="juce.h" compile="0" resource="0" file="juce.h"/>
|
||||
<FILE id="G2j0wJTna" name="juce_Config.h" compile="0" resource="0"
|
||||
|
|
|
|||
|
|
@ -147,6 +147,7 @@
|
|||
#include "../src/threads/juce_ThreadPool.cpp"
|
||||
#include "../src/threads/juce_TimeSliceThread.cpp"
|
||||
#include "../src/utilities/juce_DeletedAtShutdown.cpp"
|
||||
#include "../src/utilities/juce_UnitTest.cpp"
|
||||
#endif
|
||||
|
||||
#if JUCE_BUILD_MISC
|
||||
|
|
|
|||
|
|
@ -1439,7 +1439,7 @@ private:
|
|||
class NonWavelabMMLock
|
||||
{
|
||||
public:
|
||||
NonWavelabMMLock() : mm (getHostType().isWavelab() ? 0 : new MessageManagerLock()) {}
|
||||
NonWavelabMMLock() : mm (getHostType().isWavelab() || getHostType().isCubaseBridged() ? 0 : new MessageManagerLock()) {}
|
||||
~NonWavelabMMLock() {}
|
||||
|
||||
private:
|
||||
|
|
@ -1448,7 +1448,7 @@ private:
|
|||
|
||||
static void checkWhetherWavelabHasChangedThread()
|
||||
{
|
||||
if (getHostType().isWavelab())
|
||||
if (getHostType().isWavelab() || getHostType().isCubaseBridged())
|
||||
MessageManager::getInstance()->setCurrentThreadAsMessageThread();
|
||||
}
|
||||
#else
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ public:
|
|||
MackieTracktionGeneric,
|
||||
SteinbergCubase4,
|
||||
SteinbergCubase5,
|
||||
SteinbergCubase5Bridged,
|
||||
SteinbergCubaseGeneric,
|
||||
SteinbergWavelab5,
|
||||
SteinbergWavelab6,
|
||||
|
|
@ -68,7 +69,12 @@ public:
|
|||
|
||||
bool isCubase() const throw()
|
||||
{
|
||||
return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubaseGeneric;
|
||||
return type == SteinbergCubase4 || type == SteinbergCubase5 || type == SteinbergCubase5Bridged || type == SteinbergCubaseGeneric;
|
||||
}
|
||||
|
||||
bool isCubaseBridged() const throw()
|
||||
{
|
||||
return type == SteinbergCubase5Bridged;
|
||||
}
|
||||
|
||||
bool isTracktion() const throw()
|
||||
|
|
@ -125,6 +131,7 @@ private:
|
|||
if (hostFilename.containsIgnoreCase ("Tracktion")) return MackieTracktionGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase4")) return SteinbergCubase4;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase5")) return SteinbergCubase5;
|
||||
if (hostFilename.containsIgnoreCase ("VSTBridgeApp")) return SteinbergCubase5Bridged;
|
||||
if (hostFilename.containsIgnoreCase ("Cubase")) return SteinbergCubaseGeneric;
|
||||
if (hostFilename.containsIgnoreCase ("Wavelab 5")) return SteinbergWavelab5;
|
||||
if (hostFilename.containsIgnoreCase ("Wavelab 6" )) return SteinbergWavelab6;
|
||||
|
|
|
|||
|
|
@ -17,12 +17,12 @@ ifeq ($(CONFIG),Debug)
|
|||
LIBDIR := build
|
||||
OBJDIR := build/intermediate/Debug
|
||||
OUTDIR := build
|
||||
CPPFLAGS := $(DEPFLAGS) -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -I "/usr/include" -I "/usr/include/freetype2"
|
||||
CPPFLAGS := $(DEPFLAGS) -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -I "/usr/include" -I "/usr/include/freetype2"
|
||||
CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0
|
||||
CXXFLAGS += $(CFLAGS)
|
||||
LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -L"/usr/X11R6/lib/" -L"../../../../../juce/bin" -lfreetype -lpthread -lrt -lX11 -lGL -lGLU -lXinerama -lasound
|
||||
LDDEPS :=
|
||||
RESFLAGS := -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -I "/usr/include" -I "/usr/include/freetype2"
|
||||
RESFLAGS := -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "LINUX=1" -D "DEBUG=1" -D "_DEBUG=1" -D "JUCE_UNIT_TESTS=1" -I "/usr/include" -I "/usr/include/freetype2"
|
||||
TARGET := JuceDemo
|
||||
BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
|
||||
endif
|
||||
|
|
@ -32,12 +32,12 @@ ifeq ($(CONFIG),Release)
|
|||
LIBDIR := build
|
||||
OBJDIR := build/intermediate/Release
|
||||
OUTDIR := build
|
||||
CPPFLAGS := $(DEPFLAGS) -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "LINUX=1" -D "NDEBUG=1" -I "/usr/include" -I "/usr/include/freetype2"
|
||||
CPPFLAGS := $(DEPFLAGS) -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "LINUX=1" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -I "/usr/include" -I "/usr/include/freetype2"
|
||||
CFLAGS += $(CPPFLAGS) $(TARGET_ARCH) -Os
|
||||
CXXFLAGS += $(CFLAGS)
|
||||
LDFLAGS += -L$(BINDIR) -L$(LIBDIR) -L"/usr/X11R6/lib/" -L"../../../../../juce/bin" -lfreetype -lpthread -lrt -lX11 -lGL -lGLU -lXinerama -lasound
|
||||
LDDEPS :=
|
||||
RESFLAGS := -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "LINUX=1" -D "NDEBUG=1" -I "/usr/include" -I "/usr/include/freetype2"
|
||||
RESFLAGS := -D "JUCER_LINUX_MAKE_7346DA2A=1" -D "LINUX=1" -D "NDEBUG=1" -D "JUCE_UNIT_TESTS=1" -I "/usr/include" -I "/usr/include/freetype2"
|
||||
TARGET := JuceDemo
|
||||
BLDCMD = $(CXX) -o $(OUTDIR)/$(TARGET) $(OBJECTS) $(LDFLAGS) $(RESOURCES) $(TARGET_ARCH)
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -190,7 +190,8 @@
|
|||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"JUCER_XCODE_MAC_F6D2F4CF=1",
|
||||
"_DEBUG=1",
|
||||
"DEBUG=1 "); }; name = Debug; };
|
||||
"DEBUG=1 ",
|
||||
"JUCE_UNIT_TESTS=1"); }; name = Debug; };
|
||||
8EF7C7FFD55219581A5075F3 = { isa = XCBuildConfiguration; buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
PREBINDING = NO;
|
||||
|
|
@ -204,7 +205,8 @@
|
|||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"JUCER_XCODE_MAC_F6D2F4CF=1",
|
||||
"_NDEBUG=1",
|
||||
"NDEBUG=1 "); }; name = Release; };
|
||||
"NDEBUG=1 ",
|
||||
"JUCE_UNIT_TESTS=1"); }; name = Release; };
|
||||
7FA986B99AFC795723E00AB0 = { isa = XCBuildConfiguration; buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
BufferSecurityCheck=""
|
||||
DebugInformationFormat="4"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions="JUCER_VS2005_78A5003;WIN32;_WINDOWS;_DEBUG"
|
||||
PreprocessorDefinitions="JUCER_VS2005_78A5003;WIN32;_WINDOWS;_DEBUG;JUCE_UNIT_TESTS=1"
|
||||
RuntimeLibrary="1"
|
||||
RuntimeTypeInfo="true"
|
||||
UsePrecompiledHeader="0"
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
InlineFunctionExpansion="1"
|
||||
StringPooling="true"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions="JUCER_VS2005_78A5003;WIN32;_WINDOWS;NDEBUG"
|
||||
PreprocessorDefinitions="JUCER_VS2005_78A5003;WIN32;_WINDOWS;NDEBUG;JUCE_UNIT_TESTS=1"
|
||||
RuntimeLibrary="0"
|
||||
RuntimeTypeInfo="true"
|
||||
UsePrecompiledHeader="0"
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
BufferSecurityCheck=""
|
||||
DebugInformationFormat="4"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions="JUCER_VS2008_78A5006;WIN32;_WINDOWS;_DEBUG"
|
||||
PreprocessorDefinitions="JUCER_VS2008_78A5006;WIN32;_WINDOWS;_DEBUG;JUCE_UNIT_TESTS=1"
|
||||
RuntimeLibrary="1"
|
||||
RuntimeTypeInfo="true"
|
||||
UsePrecompiledHeader="0"
|
||||
|
|
@ -89,7 +89,7 @@
|
|||
InlineFunctionExpansion="1"
|
||||
StringPooling="true"
|
||||
AdditionalIncludeDirectories=""
|
||||
PreprocessorDefinitions="JUCER_VS2008_78A5006;WIN32;_WINDOWS;NDEBUG"
|
||||
PreprocessorDefinitions="JUCER_VS2008_78A5006;WIN32;_WINDOWS;NDEBUG;JUCE_UNIT_TESTS=1"
|
||||
RuntimeLibrary="0"
|
||||
RuntimeTypeInfo="true"
|
||||
UsePrecompiledHeader="0"
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@
|
|||
<Optimization>Disabled</Optimization>
|
||||
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>JUCER_VS2010_78A501D;WIN32;_WINDOWS;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>JUCER_VS2010_78A501D;WIN32;_WINDOWS;_DEBUG;JUCE_UNIT_TESTS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
|
|
@ -92,7 +92,7 @@
|
|||
<ClCompile>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<PreprocessorDefinitions>JUCER_VS2010_78A501D;WIN32;_WINDOWS;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions>JUCER_VS2010_78A501D;WIN32;_WINDOWS;NDEBUG;JUCE_UNIT_TESTS=1;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<PrecompiledHeader/>
|
||||
|
|
|
|||
|
|
@ -175,7 +175,8 @@
|
|||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"JUCER_XCODE_IPHONE_25ADD7EF=1",
|
||||
"_DEBUG=1",
|
||||
"DEBUG=1 "); }; name = Debug; };
|
||||
"DEBUG=1 ",
|
||||
"JUCE_UNIT_TESTS=1"); }; name = Debug; };
|
||||
8EF7C7FFD55219581A5075F3 = { isa = XCBuildConfiguration; buildSettings = {
|
||||
ARCHS = "$(ARCHS_STANDARD_32_BIT)";
|
||||
PREBINDING = NO;
|
||||
|
|
@ -189,7 +190,8 @@
|
|||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"JUCER_XCODE_IPHONE_25ADD7EF=1",
|
||||
"_NDEBUG=1",
|
||||
"NDEBUG=1 "); }; name = Release; };
|
||||
"NDEBUG=1 ",
|
||||
"JUCE_UNIT_TESTS=1"); }; name = Release; };
|
||||
7FA986B99AFC795723E00AB0 = { isa = XCBuildConfiguration; buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = c99;
|
||||
|
|
|
|||
|
|
@ -24,9 +24,9 @@
|
|||
</EXPORTFORMATS>
|
||||
<CONFIGURATIONS>
|
||||
<CONFIGURATION name="Debug" isDebug="1" optimisation="1" targetName="JuceDemo"
|
||||
osxSDK="default" osxCompatibility="default"/>
|
||||
osxSDK="default" osxCompatibility="default" defines="JUCE_UNIT_TESTS=1"/>
|
||||
<CONFIGURATION name="Release" isDebug="0" optimisation="2" targetName="JuceDemo"
|
||||
osxSDK="default" osxCompatibility="default"/>
|
||||
osxSDK="default" osxCompatibility="default" defines="JUCE_UNIT_TESTS=1"/>
|
||||
</CONFIGURATIONS>
|
||||
<MAINGROUP id="0bU7ypLe" name="Juce Demo">
|
||||
<GROUP id="BEJsSEFfF" name="Source">
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -64,7 +64,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 59
|
||||
#define JUCE_BUILDNUMBER 60
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
@ -1757,36 +1757,43 @@ public:
|
|||
int compareLexicographically (const String& other) const throw();
|
||||
|
||||
/** Tests whether the string begins with another string.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool startsWith (const String& text) const throw();
|
||||
|
||||
/** Tests whether the string begins with a particular character.
|
||||
If the character is 0, this will always return false.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool startsWithChar (juce_wchar character) const throw();
|
||||
|
||||
/** Tests whether the string begins with another string.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-insensitive comparison.
|
||||
*/
|
||||
bool startsWithIgnoreCase (const String& text) const throw();
|
||||
|
||||
/** Tests whether the string ends with another string.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool endsWith (const String& text) const throw();
|
||||
|
||||
/** Tests whether the string ends with a particular character.
|
||||
If the character is 0, this will always return false.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool endsWithChar (juce_wchar character) const throw();
|
||||
|
||||
/** Tests whether the string ends with another string.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-insensitive comparison.
|
||||
*/
|
||||
bool endsWithIgnoreCase (const String& text) const throw();
|
||||
|
||||
/** Tests whether the string contains another substring.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool contains (const String& text) const throw();
|
||||
|
|
@ -13870,7 +13877,6 @@ public:
|
|||
private:
|
||||
File logFile;
|
||||
CriticalSection logLock;
|
||||
ScopedPointer <FileOutputStream> logStream;
|
||||
|
||||
void trimFileSize (int maxFileSizeBytes) const;
|
||||
|
||||
|
|
@ -61385,6 +61391,221 @@ public:
|
|||
#endif
|
||||
#ifndef __JUCE_UNDOMANAGER_JUCEHEADER__
|
||||
|
||||
#endif
|
||||
#ifndef __JUCE_UNITTEST_JUCEHEADER__
|
||||
|
||||
/*** Start of inlined file: juce_UnitTest.h ***/
|
||||
#ifndef __JUCE_UNITTEST_JUCEHEADER__
|
||||
#define __JUCE_UNITTEST_JUCEHEADER__
|
||||
|
||||
class UnitTestRunner;
|
||||
|
||||
/**
|
||||
This is a base class for classes that perform a unit test.
|
||||
|
||||
To write a test using this class, your code should look something like this:
|
||||
|
||||
@code
|
||||
class MyTest : public UnitTest
|
||||
{
|
||||
public:
|
||||
MyTest() : UnitTest ("Foobar testing") {}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
beginTest ("Part 1");
|
||||
|
||||
expect (myFoobar.doesSomething());
|
||||
expect (myFoobar.doesSomethingElse());
|
||||
|
||||
beginTest ("Part 2");
|
||||
|
||||
expect (myOtherFoobar.doesSomething());
|
||||
expect (myOtherFoobar.doesSomethingElse());
|
||||
|
||||
...etc..
|
||||
}
|
||||
};
|
||||
|
||||
// Creating a static instance will automatically add the instance to the array
|
||||
// returned by UnitTest::getAllTests(), so the test will be included when you call
|
||||
// UnitTestRunner::runAllTests()
|
||||
static MyTest test;
|
||||
@endcode
|
||||
|
||||
To run a test, use the UnitTestRunner class.
|
||||
|
||||
@see UnitTestRunner
|
||||
*/
|
||||
class UnitTest
|
||||
{
|
||||
public:
|
||||
|
||||
/** Creates a test with the given name. */
|
||||
UnitTest (const String& name);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~UnitTest();
|
||||
|
||||
/** Returns the name of the test. */
|
||||
const String getName() const throw() { return name; }
|
||||
|
||||
/** Runs the test, using the specified UnitTestRunner.
|
||||
You shouldn't need to call this method directly - use
|
||||
UnitTestRunner::runTests() instead.
|
||||
*/
|
||||
void performTest (UnitTestRunner* runner);
|
||||
|
||||
/** Returns the set of all UnitTest objects that currently exist. */
|
||||
static Array<UnitTest*>& getAllTests();
|
||||
|
||||
/** Implement this method in your subclass to actually run your tests.
|
||||
|
||||
The content of your implementation should call beginTest() and expect()
|
||||
to perform the tests.
|
||||
*/
|
||||
virtual void runTest() = 0;
|
||||
|
||||
/** Tells the system that a new subsection of tests is beginning.
|
||||
This should be called from your runTest() method, and may be called
|
||||
as many times as you like, to demarcate different sets of tests.
|
||||
*/
|
||||
void beginTest (const String& testName);
|
||||
|
||||
/** Checks that the result of a test is true, and logs this result.
|
||||
|
||||
In your runTest() method, you should call this method for each condition that
|
||||
you want to check, e.g.
|
||||
|
||||
@code
|
||||
void runTest()
|
||||
{
|
||||
beginTest ("basic tests");
|
||||
expect (x + y == 2);
|
||||
expect (getThing() == someThing);
|
||||
...etc...
|
||||
}
|
||||
@endcode
|
||||
|
||||
If testResult is true, a pass is logged; if it's false, a failure is logged.
|
||||
If the failure message is specified, it will be written to the log if the test fails.
|
||||
*/
|
||||
void expect (bool testResult, const String& failureMessage = String::empty);
|
||||
|
||||
/** Writes a message to the test log.
|
||||
This can only be called from within your runTest() method.
|
||||
*/
|
||||
void logMessage (const String& message);
|
||||
|
||||
private:
|
||||
|
||||
const String name;
|
||||
UnitTestRunner* runner;
|
||||
|
||||
UnitTest (const UnitTest&);
|
||||
UnitTest& operator= (const UnitTest&);
|
||||
};
|
||||
|
||||
/**
|
||||
Runs a set of unit tests.
|
||||
|
||||
You can instantiate one of these objects and use it to invoke tests on a set of
|
||||
UnitTest objects.
|
||||
|
||||
By using a subclass of UnitTestRunner, you can intercept logging messages and
|
||||
perform custom behaviour when each test completes.
|
||||
|
||||
@see UnitTest
|
||||
*/
|
||||
class UnitTestRunner
|
||||
{
|
||||
public:
|
||||
|
||||
/** */
|
||||
UnitTestRunner();
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~UnitTestRunner();
|
||||
|
||||
/** Runs a set of tests.
|
||||
|
||||
The tests are performed in order, and the results are logged. To run all the
|
||||
registered UnitTest objects that exist, use runAllTests().
|
||||
*/
|
||||
void runTests (const Array<UnitTest*>& tests, bool assertOnFailure);
|
||||
|
||||
/** Runs all the UnitTest objects that currently exist.
|
||||
This calls runTests() for all the objects listed in UnitTest::getAllTests().
|
||||
*/
|
||||
void runAllTests (bool assertOnFailure);
|
||||
|
||||
/** Contains the results of a test.
|
||||
|
||||
One of these objects is instantiated each time UnitTest::beginTest() is called, and
|
||||
it contains details of the number of subsequent UnitTest::expect() calls that are
|
||||
made.
|
||||
*/
|
||||
struct TestResult
|
||||
{
|
||||
/** The main name of this test (i.e. the name of the UnitTest object being run). */
|
||||
String unitTestName;
|
||||
/** The name of the current subcategory (i.e. the name that was set when UnitTest::beginTest() was called). */
|
||||
String subcategoryName;
|
||||
|
||||
/** The number of UnitTest::expect() calls that succeeded. */
|
||||
int passes;
|
||||
/** The number of UnitTest::expect() calls that failed. */
|
||||
int failures;
|
||||
|
||||
/** A list of messages describing the failed tests. */
|
||||
StringArray messages;
|
||||
};
|
||||
|
||||
/** Returns the number of TestResult objects that have been performed.
|
||||
@see getResult
|
||||
*/
|
||||
int getNumResults() const throw();
|
||||
|
||||
/** Returns one of the TestResult objects that describes a test that has been run.
|
||||
@see getNumResults
|
||||
*/
|
||||
const TestResult* getResult (int index) const throw();
|
||||
|
||||
protected:
|
||||
/** Called when the list of results changes.
|
||||
You can override this to perform some sort of behaviour when results are added.
|
||||
*/
|
||||
virtual void resultsUpdated();
|
||||
|
||||
/** Logs a message about the current test progress.
|
||||
By default this just writes the message to the Logger class, but you could override
|
||||
this to do something else with the data.
|
||||
*/
|
||||
virtual void logMessage (const String& message);
|
||||
|
||||
private:
|
||||
|
||||
friend class UnitTest;
|
||||
|
||||
UnitTest* currentTest;
|
||||
String currentSubCategory;
|
||||
OwnedArray <TestResult, CriticalSection> results;
|
||||
bool assertOnFailure;
|
||||
|
||||
void beginNewTest (UnitTest* test, const String& subCategory);
|
||||
void endTest();
|
||||
|
||||
void addPass();
|
||||
void addFail (const String& failureMessage);
|
||||
|
||||
UnitTestRunner (const UnitTestRunner&);
|
||||
UnitTestRunner& operator= (const UnitTestRunner&);
|
||||
};
|
||||
|
||||
#endif // __JUCE_UNITTEST_JUCEHEADER__
|
||||
/*** End of inlined file: juce_UnitTest.h ***/
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -50,9 +50,6 @@ FileLogger::FileLogger (const File& logFile_,
|
|||
logFile_.create();
|
||||
}
|
||||
|
||||
logStream = logFile_.createOutputStream (256);
|
||||
jassert (logStream != 0);
|
||||
|
||||
String welcome;
|
||||
welcome << "\r\n**********************************************************\r\n"
|
||||
<< welcomeMessage
|
||||
|
|
@ -69,14 +66,12 @@ FileLogger::~FileLogger()
|
|||
//==============================================================================
|
||||
void FileLogger::logMessage (const String& message)
|
||||
{
|
||||
if (logStream != 0)
|
||||
{
|
||||
DBG (message);
|
||||
DBG (message);
|
||||
|
||||
const ScopedLock sl (logLock);
|
||||
(*logStream) << message << "\r\n";
|
||||
logStream->flush();
|
||||
}
|
||||
const ScopedLock sl (logLock);
|
||||
|
||||
FileOutputStream out (logFile, 256);
|
||||
out << message << "\r\n";
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -100,7 +100,6 @@ public:
|
|||
private:
|
||||
File logFile;
|
||||
CriticalSection logLock;
|
||||
ScopedPointer <FileOutputStream> logStream;
|
||||
|
||||
void trimFileSize (int maxFileSizeBytes) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -50,125 +50,6 @@ BEGIN_JUCE_NAMESPACE
|
|||
extern void juce_CheckForDanglingStreams(); // (in juce_OutputStream.cpp)
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_DEBUG
|
||||
|
||||
namespace SimpleUnitTests
|
||||
{
|
||||
template <typename Type>
|
||||
class AtomicTester
|
||||
{
|
||||
public:
|
||||
AtomicTester() {}
|
||||
|
||||
static void testInteger()
|
||||
{
|
||||
Atomic<Type> a, b;
|
||||
a.set ((Type) 10);
|
||||
a += (Type) 15;
|
||||
a.memoryBarrier();
|
||||
a -= (Type) 5;
|
||||
++a; ++a; --a;
|
||||
a.memoryBarrier();
|
||||
|
||||
testFloat();
|
||||
}
|
||||
|
||||
static void testFloat()
|
||||
{
|
||||
Atomic<Type> a, b;
|
||||
a = (Type) 21;
|
||||
a.memoryBarrier();
|
||||
|
||||
/* These are some simple test cases to check the atomics - let me know
|
||||
if any of these assertions fail on your system!
|
||||
*/
|
||||
jassert (a.get() == (Type) 21);
|
||||
jassert (a.compareAndSetValue ((Type) 100, (Type) 50) == (Type) 21);
|
||||
jassert (a.get() == (Type) 21);
|
||||
jassert (a.compareAndSetValue ((Type) 101, a.get()) == (Type) 21);
|
||||
jassert (a.get() == (Type) 101);
|
||||
jassert (! a.compareAndSetBool ((Type) 300, (Type) 200));
|
||||
jassert (a.get() == (Type) 101);
|
||||
jassert (a.compareAndSetBool ((Type) 200, a.get()));
|
||||
jassert (a.get() == (Type) 200);
|
||||
|
||||
jassert (a.exchange ((Type) 300) == (Type) 200);
|
||||
jassert (a.get() == (Type) 300);
|
||||
|
||||
b = a;
|
||||
jassert (b.get() == a.get());
|
||||
}
|
||||
};
|
||||
|
||||
static void runBasicTests()
|
||||
{
|
||||
// Some simple test code, to keep an eye on things and make sure these functions
|
||||
// work ok on all platforms. Let me know if any of these assertions fail on your system!
|
||||
|
||||
static_jassert (sizeof (pointer_sized_int) == sizeof (void*));
|
||||
static_jassert (sizeof (int8) == 1);
|
||||
static_jassert (sizeof (uint8) == 1);
|
||||
static_jassert (sizeof (int16) == 2);
|
||||
static_jassert (sizeof (uint16) == 2);
|
||||
static_jassert (sizeof (int32) == 4);
|
||||
static_jassert (sizeof (uint32) == 4);
|
||||
static_jassert (sizeof (int64) == 8);
|
||||
static_jassert (sizeof (uint64) == 8);
|
||||
|
||||
char a1[7];
|
||||
jassert (numElementsInArray(a1) == 7);
|
||||
int a2[3];
|
||||
jassert (numElementsInArray(a2) == 3);
|
||||
|
||||
jassert (ByteOrder::swap ((uint16) 0x1122) == 0x2211);
|
||||
jassert (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211);
|
||||
jassert (ByteOrder::swap ((uint64) literal64bit (0x1122334455667788)) == literal64bit (0x8877665544332211));
|
||||
|
||||
// Some quick stream tests..
|
||||
int randomInt = Random::getSystemRandom().nextInt();
|
||||
int64 randomInt64 = Random::getSystemRandom().nextInt64();
|
||||
double randomDouble = Random::getSystemRandom().nextDouble();
|
||||
String randomString;
|
||||
for (int i = 50; --i >= 0;)
|
||||
randomString << (juce_wchar) (Random::getSystemRandom().nextInt() & 0xffff);
|
||||
|
||||
MemoryOutputStream mo;
|
||||
mo.writeInt (randomInt);
|
||||
mo.writeIntBigEndian (randomInt);
|
||||
mo.writeCompressedInt (randomInt);
|
||||
mo.writeString (randomString);
|
||||
mo.writeInt64 (randomInt64);
|
||||
mo.writeInt64BigEndian (randomInt64);
|
||||
mo.writeDouble (randomDouble);
|
||||
mo.writeDoubleBigEndian (randomDouble);
|
||||
|
||||
MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);
|
||||
jassert (mi.readInt() == randomInt);
|
||||
jassert (mi.readIntBigEndian() == randomInt);
|
||||
jassert (mi.readCompressedInt() == randomInt);
|
||||
jassert (mi.readString() == randomString);
|
||||
jassert (mi.readInt64() == randomInt64);
|
||||
jassert (mi.readInt64BigEndian() == randomInt64);
|
||||
jassert (mi.readDouble() == randomDouble);
|
||||
jassert (mi.readDoubleBigEndian() == randomDouble);
|
||||
|
||||
AtomicTester <int>::testInteger();
|
||||
AtomicTester <unsigned int>::testInteger();
|
||||
AtomicTester <int32>::testInteger();
|
||||
AtomicTester <uint32>::testInteger();
|
||||
AtomicTester <long>::testInteger();
|
||||
AtomicTester <void*>::testInteger();
|
||||
AtomicTester <int*>::testInteger();
|
||||
AtomicTester <float>::testFloat();
|
||||
#if ! JUCE_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms
|
||||
AtomicTester <int64>::testInteger();
|
||||
AtomicTester <uint64>::testInteger();
|
||||
AtomicTester <double>::testFloat();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
static bool juceInitialisedNonGUI = false;
|
||||
|
|
@ -181,14 +62,22 @@ void JUCE_PUBLIC_FUNCTION initialiseJuce_NonGUI()
|
|||
|
||||
JUCE_AUTORELEASEPOOL
|
||||
|
||||
#if JUCE_DEBUG
|
||||
SimpleUnitTests::runBasicTests();
|
||||
#endif
|
||||
|
||||
DBG (SystemStats::getJUCEVersion());
|
||||
SystemStats::initialiseStats();
|
||||
Random::getSystemRandom().setSeedRandomly(); // (mustn't call this before initialiseStats() because it relies on the time being set up)
|
||||
}
|
||||
|
||||
// Some basic tests, to keep an eye on things and make sure these types work ok
|
||||
// on all platforms. Let me know if any of these assertions fail on your system!
|
||||
static_jassert (sizeof (pointer_sized_int) == sizeof (void*));
|
||||
static_jassert (sizeof (int8) == 1);
|
||||
static_jassert (sizeof (uint8) == 1);
|
||||
static_jassert (sizeof (int16) == 2);
|
||||
static_jassert (sizeof (uint16) == 2);
|
||||
static_jassert (sizeof (int32) == 4);
|
||||
static_jassert (sizeof (uint32) == 4);
|
||||
static_jassert (sizeof (int64) == 8);
|
||||
static_jassert (sizeof (uint64) == 8);
|
||||
}
|
||||
|
||||
void JUCE_PUBLIC_FUNCTION shutdownJuce_NonGUI()
|
||||
|
|
@ -269,4 +158,95 @@ void JUCE_PUBLIC_FUNCTION shutdownJuce_GUI()
|
|||
|
||||
#endif
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
#include "../utilities/juce_UnitTest.h"
|
||||
|
||||
class AtomicTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
AtomicTests() : UnitTest ("Atomics") {}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
beginTest ("Misc");
|
||||
|
||||
char a1[7];
|
||||
expect (numElementsInArray(a1) == 7);
|
||||
int a2[3];
|
||||
expect (numElementsInArray(a2) == 3);
|
||||
|
||||
expect (ByteOrder::swap ((uint16) 0x1122) == 0x2211);
|
||||
expect (ByteOrder::swap ((uint32) 0x11223344) == 0x44332211);
|
||||
expect (ByteOrder::swap ((uint64) literal64bit (0x1122334455667788)) == literal64bit (0x8877665544332211));
|
||||
|
||||
beginTest ("Atomic types");
|
||||
AtomicTester <int>::testInteger (*this);
|
||||
AtomicTester <unsigned int>::testInteger (*this);
|
||||
AtomicTester <int32>::testInteger (*this);
|
||||
AtomicTester <uint32>::testInteger (*this);
|
||||
AtomicTester <long>::testInteger (*this);
|
||||
AtomicTester <void*>::testInteger (*this);
|
||||
AtomicTester <int*>::testInteger (*this);
|
||||
AtomicTester <float>::testFloat (*this);
|
||||
#if ! JUCE_64BIT_ATOMICS_UNAVAILABLE // 64-bit intrinsics aren't available on some old platforms
|
||||
AtomicTester <int64>::testInteger (*this);
|
||||
AtomicTester <uint64>::testInteger (*this);
|
||||
AtomicTester <double>::testFloat (*this);
|
||||
#endif
|
||||
}
|
||||
|
||||
template <typename Type>
|
||||
class AtomicTester
|
||||
{
|
||||
public:
|
||||
AtomicTester() {}
|
||||
|
||||
static void testInteger (UnitTest& test)
|
||||
{
|
||||
Atomic<Type> a, b;
|
||||
a.set ((Type) 10);
|
||||
a += (Type) 15;
|
||||
a.memoryBarrier();
|
||||
a -= (Type) 5;
|
||||
++a; ++a; --a;
|
||||
a.memoryBarrier();
|
||||
|
||||
testFloat (test);
|
||||
}
|
||||
|
||||
static void testFloat (UnitTest& test)
|
||||
{
|
||||
Atomic<Type> a, b;
|
||||
a = (Type) 21;
|
||||
a.memoryBarrier();
|
||||
|
||||
/* These are some simple test cases to check the atomics - let me know
|
||||
if any of these assertions fail on your system!
|
||||
*/
|
||||
test.expect (a.get() == (Type) 21);
|
||||
test.expect (a.compareAndSetValue ((Type) 100, (Type) 50) == (Type) 21);
|
||||
test.expect (a.get() == (Type) 21);
|
||||
test.expect (a.compareAndSetValue ((Type) 101, a.get()) == (Type) 21);
|
||||
test.expect (a.get() == (Type) 101);
|
||||
test.expect (! a.compareAndSetBool ((Type) 300, (Type) 200));
|
||||
test.expect (a.get() == (Type) 101);
|
||||
test.expect (a.compareAndSetBool ((Type) 200, a.get()));
|
||||
test.expect (a.get() == (Type) 200);
|
||||
|
||||
test.expect (a.exchange ((Type) 300) == (Type) 200);
|
||||
test.expect (a.get() == (Type) 300);
|
||||
|
||||
b = a;
|
||||
test.expect (b.get() == a.get());
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
static AtomicTests atomicUnitTests;
|
||||
|
||||
#endif
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
*/
|
||||
#define JUCE_MAJOR_VERSION 1
|
||||
#define JUCE_MINOR_VERSION 52
|
||||
#define JUCE_BUILDNUMBER 59
|
||||
#define JUCE_BUILDNUMBER 60
|
||||
|
||||
/** Current Juce version number.
|
||||
|
||||
|
|
|
|||
|
|
@ -570,7 +570,8 @@ int File::findChildFiles (Array<File>& results,
|
|||
}
|
||||
|
||||
if (searchRecursively && itemIsDirectory
|
||||
&& fileTypeMatches (whatToLookFor | findDirectories, true, itemIsHidden))
|
||||
&& ((! itemIsHidden) || (whatToLookFor & File::ignoreHiddenFiles) == 0))
|
||||
|
||||
{
|
||||
total += fileFound.findChildFiles (results, whatToLookFor, true, wildCardPattern);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,4 +92,53 @@ int64 MemoryInputStream::getPosition()
|
|||
return position;
|
||||
}
|
||||
|
||||
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
#include "../../utilities/juce_UnitTest.h"
|
||||
#include "../../core/juce_Random.h"
|
||||
#include "juce_MemoryOutputStream.h"
|
||||
|
||||
class MemoryStreamTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
MemoryStreamTests() : UnitTest ("MemoryInputStream & MemoryOutputStream") {}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
beginTest ("Basics");
|
||||
|
||||
int randomInt = Random::getSystemRandom().nextInt();
|
||||
int64 randomInt64 = Random::getSystemRandom().nextInt64();
|
||||
double randomDouble = Random::getSystemRandom().nextDouble();
|
||||
String randomString;
|
||||
for (int i = 50; --i >= 0;)
|
||||
randomString << (juce_wchar) (Random::getSystemRandom().nextInt() & 0xffff);
|
||||
|
||||
MemoryOutputStream mo;
|
||||
mo.writeInt (randomInt);
|
||||
mo.writeIntBigEndian (randomInt);
|
||||
mo.writeCompressedInt (randomInt);
|
||||
mo.writeString (randomString);
|
||||
mo.writeInt64 (randomInt64);
|
||||
mo.writeInt64BigEndian (randomInt64);
|
||||
mo.writeDouble (randomDouble);
|
||||
mo.writeDoubleBigEndian (randomDouble);
|
||||
|
||||
MemoryInputStream mi (mo.getData(), mo.getDataSize(), false);
|
||||
expect (mi.readInt() == randomInt);
|
||||
expect (mi.readIntBigEndian() == randomInt);
|
||||
expect (mi.readCompressedInt() == randomInt);
|
||||
expect (mi.readString() == randomString);
|
||||
expect (mi.readInt64() == randomInt64);
|
||||
expect (mi.readInt64BigEndian() == randomInt64);
|
||||
expect (mi.readDouble() == randomDouble);
|
||||
expect (mi.readDoubleBigEndian() == randomDouble);
|
||||
}
|
||||
};
|
||||
|
||||
static MemoryStreamTests memoryInputStreamUnitTests;
|
||||
|
||||
#endif
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -758,5 +758,8 @@
|
|||
#ifndef __JUCE_UNDOMANAGER_JUCEHEADER__
|
||||
#include "utilities/juce_UndoManager.h"
|
||||
#endif
|
||||
#ifndef __JUCE_UNITTEST_JUCEHEADER__
|
||||
#include "utilities/juce_UnitTest.h"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -28,15 +28,6 @@
|
|||
#if JUCE_INCLUDED_FILE
|
||||
|
||||
//==============================================================================
|
||||
using ::free;
|
||||
|
||||
namespace MidiConstants
|
||||
{
|
||||
static const int midiBufferSize = 1024 * 10;
|
||||
static const int numInHeaders = 32;
|
||||
static const int inBufferSize = 256;
|
||||
}
|
||||
|
||||
class MidiInThread : public Thread
|
||||
{
|
||||
public:
|
||||
|
|
@ -44,18 +35,19 @@ public:
|
|||
MidiInThread (MidiInput* const input_,
|
||||
MidiInputCallback* const callback_)
|
||||
: Thread ("Juce Midi"),
|
||||
hIn (0),
|
||||
deviceHandle (0),
|
||||
input (input_),
|
||||
callback (callback_),
|
||||
isStarted (false),
|
||||
startTime (0),
|
||||
pendingLength(0)
|
||||
startTime (0)
|
||||
{
|
||||
for (int i = MidiConstants::numInHeaders; --i >= 0;)
|
||||
pending.ensureSize ((int) defaultBufferSize);
|
||||
|
||||
for (int i = (int) numInHeaders; --i >= 0;)
|
||||
{
|
||||
zeromem (&hdr[i], sizeof (MIDIHDR));
|
||||
hdr[i].lpData = inData[i];
|
||||
hdr[i].dwBufferLength = MidiConstants::inBufferSize;
|
||||
hdr[i].dwBufferLength = (int) inBufferSize;
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -63,12 +55,12 @@ public:
|
|||
{
|
||||
stop();
|
||||
|
||||
if (hIn != 0)
|
||||
if (deviceHandle != 0)
|
||||
{
|
||||
int count = 5;
|
||||
while (--count >= 0)
|
||||
{
|
||||
if (midiInClose (hIn) == MMSYSERR_NOERROR)
|
||||
if (midiInClose (deviceHandle) == MMSYSERR_NOERROR)
|
||||
break;
|
||||
|
||||
Sleep (20);
|
||||
|
|
@ -83,24 +75,11 @@ public:
|
|||
if (byte < 0x80)
|
||||
return;
|
||||
|
||||
const int numBytes = MidiMessage::getMessageLengthFromFirstByte ((uint8) byte);
|
||||
const double time = timeStampToTime (timeStamp);
|
||||
const int time = timeStampToMs (timeStamp);
|
||||
|
||||
{
|
||||
const ScopedLock sl (lock);
|
||||
|
||||
if (pendingLength < MidiConstants::midiBufferSize - 12)
|
||||
{
|
||||
char* const p = pending + pendingLength;
|
||||
*(double*) p = time;
|
||||
*(uint32*) (p + 8) = numBytes;
|
||||
*(uint32*) (p + 12) = message;
|
||||
pendingLength += 12 + numBytes;
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse; // midi buffer overflow! You might need to increase the size..
|
||||
}
|
||||
pending.addEvent (&message, 3, time);
|
||||
}
|
||||
|
||||
notify();
|
||||
|
|
@ -108,27 +87,14 @@ public:
|
|||
|
||||
void handleSysEx (MIDIHDR* const hdr, const uint32 timeStamp)
|
||||
{
|
||||
const int time = timeStampToMs (timeStamp);
|
||||
const int num = hdr->dwBytesRecorded;
|
||||
|
||||
if (num > 0)
|
||||
{
|
||||
const double time = timeStampToTime (timeStamp);
|
||||
|
||||
{
|
||||
const ScopedLock sl (lock);
|
||||
|
||||
if (pendingLength < MidiConstants::midiBufferSize - (8 + num))
|
||||
{
|
||||
char* const p = pending + pendingLength;
|
||||
*(double*) p = time;
|
||||
*(uint32*) (p + 8) = num;
|
||||
memcpy (p + 12, hdr->lpData, num);
|
||||
pendingLength += 12 + num;
|
||||
}
|
||||
else
|
||||
{
|
||||
jassertfalse; // midi buffer overflow! You might need to increase the size..
|
||||
}
|
||||
pending.addEvent (hdr->lpData, num, time);
|
||||
}
|
||||
|
||||
notify();
|
||||
|
|
@ -138,65 +104,52 @@ public:
|
|||
void writeBlock (const int i)
|
||||
{
|
||||
hdr[i].dwBytesRecorded = 0;
|
||||
MMRESULT res = midiInPrepareHeader (hIn, &hdr[i], sizeof (MIDIHDR));
|
||||
MMRESULT res = midiInPrepareHeader (deviceHandle, &hdr[i], sizeof (MIDIHDR));
|
||||
jassert (res == MMSYSERR_NOERROR);
|
||||
res = midiInAddBuffer (hIn, &hdr[i], sizeof (MIDIHDR));
|
||||
res = midiInAddBuffer (deviceHandle, &hdr[i], sizeof (MIDIHDR));
|
||||
jassert (res == MMSYSERR_NOERROR);
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
MemoryBlock pendingCopy (64);
|
||||
MidiBuffer newEvents;
|
||||
newEvents.ensureSize ((int) defaultBufferSize);
|
||||
|
||||
while (! threadShouldExit())
|
||||
{
|
||||
for (int i = 0; i < MidiConstants::numInHeaders; ++i)
|
||||
for (int i = 0; i < (int) numInHeaders; ++i)
|
||||
{
|
||||
if ((hdr[i].dwFlags & WHDR_DONE) != 0)
|
||||
{
|
||||
MMRESULT res = midiInUnprepareHeader (hIn, &hdr[i], sizeof (MIDIHDR));
|
||||
MMRESULT res = midiInUnprepareHeader (deviceHandle, &hdr[i], sizeof (MIDIHDR));
|
||||
(void) res;
|
||||
jassert (res == MMSYSERR_NOERROR);
|
||||
writeBlock (i);
|
||||
}
|
||||
}
|
||||
|
||||
int len;
|
||||
newEvents.clear(); // (resets it without freeing allocated storage)
|
||||
|
||||
{
|
||||
const ScopedLock sl (lock);
|
||||
|
||||
len = pendingLength;
|
||||
|
||||
if (len > 0)
|
||||
{
|
||||
pendingCopy.ensureSize (len);
|
||||
pendingCopy.copyFrom (pending, 0, len);
|
||||
pendingLength = 0;
|
||||
}
|
||||
newEvents.swapWith (pending);
|
||||
}
|
||||
|
||||
//xxx needs to figure out if blocks are broken up or not
|
||||
|
||||
if (len == 0)
|
||||
if (newEvents.isEmpty())
|
||||
{
|
||||
wait (500);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* p = (const char*) pendingCopy.getData();
|
||||
MidiMessage message (0xf4, 0.0);
|
||||
int time;
|
||||
|
||||
while (len > 0)
|
||||
for (MidiBuffer::Iterator i (newEvents); i.getNextEvent (message, time);)
|
||||
{
|
||||
const double time = *(const double*) p;
|
||||
const int messageLen = *(const int*) (p + 8);
|
||||
|
||||
const MidiMessage message ((const uint8*) (p + 12), messageLen, time);
|
||||
|
||||
message.setTimeStamp (time * 0.001);
|
||||
callback->handleIncomingMidiMessage (input, message);
|
||||
|
||||
p += 12 + messageLen;
|
||||
len -= 12 + messageLen;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -204,26 +157,25 @@ public:
|
|||
|
||||
void start()
|
||||
{
|
||||
jassert (hIn != 0);
|
||||
if (hIn != 0 && ! isStarted)
|
||||
jassert (deviceHandle != 0);
|
||||
if (deviceHandle != 0 && ! isStarted)
|
||||
{
|
||||
stop();
|
||||
|
||||
activeMidiThreads.addIfNotAlreadyThere (this);
|
||||
|
||||
int i;
|
||||
for (i = 0; i < MidiConstants::numInHeaders; ++i)
|
||||
for (i = 0; i < (int) numInHeaders; ++i)
|
||||
writeBlock (i);
|
||||
|
||||
startTime = Time::getMillisecondCounter();
|
||||
MMRESULT res = midiInStart (hIn);
|
||||
|
||||
MMRESULT res = midiInStart (deviceHandle);
|
||||
jassert (res == MMSYSERR_NOERROR);
|
||||
|
||||
if (res == MMSYSERR_NOERROR)
|
||||
{
|
||||
isStarted = true;
|
||||
pendingLength = 0;
|
||||
pending.clear();
|
||||
startThread (6);
|
||||
}
|
||||
}
|
||||
|
|
@ -235,19 +187,19 @@ public:
|
|||
{
|
||||
stopThread (5000);
|
||||
|
||||
midiInReset (hIn);
|
||||
midiInStop (hIn);
|
||||
midiInReset (deviceHandle);
|
||||
midiInStop (deviceHandle);
|
||||
|
||||
activeMidiThreads.removeValue (this);
|
||||
|
||||
{ const ScopedLock sl (lock); }
|
||||
|
||||
for (int i = MidiConstants::numInHeaders; --i >= 0;)
|
||||
for (int i = (int) numInHeaders; --i >= 0;)
|
||||
{
|
||||
if ((hdr[i].dwFlags & WHDR_DONE) != 0)
|
||||
{
|
||||
int c = 10;
|
||||
while (--c >= 0 && midiInUnprepareHeader (hIn, &hdr[i], sizeof (MIDIHDR)) == MIDIERR_STILLPLAYING)
|
||||
while (--c >= 0 && midiInUnprepareHeader (deviceHandle, &hdr[i], sizeof (MIDIHDR)) == MIDIERR_STILLPLAYING)
|
||||
Sleep (20);
|
||||
|
||||
jassert (c >= 0);
|
||||
|
|
@ -255,7 +207,7 @@ public:
|
|||
}
|
||||
|
||||
isStarted = false;
|
||||
pendingLength = 0;
|
||||
pending.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -274,7 +226,7 @@ public:
|
|||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
HMIDIIN hIn;
|
||||
HMIDIIN deviceHandle;
|
||||
|
||||
private:
|
||||
static Array <void*, CriticalSection> activeMidiThreads;
|
||||
|
|
@ -285,13 +237,16 @@ private:
|
|||
uint32 startTime;
|
||||
CriticalSection lock;
|
||||
|
||||
MIDIHDR hdr [MidiConstants::numInHeaders];
|
||||
char inData [MidiConstants::numInHeaders] [MidiConstants::inBufferSize];
|
||||
enum { defaultBufferSize = 8192,
|
||||
numInHeaders = 32,
|
||||
inBufferSize = 256 };
|
||||
|
||||
int pendingLength;
|
||||
char pending [MidiConstants::midiBufferSize];
|
||||
MIDIHDR hdr [(int) numInHeaders];
|
||||
char inData [(int) numInHeaders] [(int) inBufferSize];
|
||||
|
||||
double timeStampToTime (uint32 timeStamp)
|
||||
MidiBuffer pending;
|
||||
|
||||
int timeStampToMs (uint32 timeStamp)
|
||||
{
|
||||
timeStamp += startTime;
|
||||
|
||||
|
|
@ -304,7 +259,7 @@ private:
|
|||
timeStamp = now;
|
||||
}
|
||||
|
||||
return 0.001 * timeStamp;
|
||||
return (int) timeStamp;
|
||||
}
|
||||
|
||||
MidiInThread (const MidiInThread&);
|
||||
|
|
@ -358,7 +313,7 @@ MidiInput* MidiInput::openDevice (const int index, MidiInputCallback* const call
|
|||
if (index == n)
|
||||
{
|
||||
deviceId = i;
|
||||
name = String (mc.szPname, sizeof (mc.szPname));
|
||||
name = String (mc.szPname, numElementsInArray (mc.szPname));
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
@ -377,7 +332,7 @@ MidiInput* MidiInput::openDevice (const int index, MidiInputCallback* const call
|
|||
|
||||
if (err == MMSYSERR_NOERROR)
|
||||
{
|
||||
thread->hIn = h;
|
||||
thread->deviceHandle = h;
|
||||
in->internal = thread.release();
|
||||
return in.release();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -967,7 +967,7 @@ private:
|
|||
|
||||
void createWindow()
|
||||
{
|
||||
DWORD exstyle = WS_EX_ACCEPTFILES;
|
||||
DWORD exstyle = WS_EX_ACCEPTFILES; // | WS_EX_NOACTIVATE;
|
||||
DWORD type = WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
|
||||
|
||||
if (hasTitleBar())
|
||||
|
|
|
|||
|
|
@ -2184,5 +2184,272 @@ void String::Concatenator::append (const String& s)
|
|||
}
|
||||
}
|
||||
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
#include "../utilities/juce_UnitTest.h"
|
||||
#include "../core/juce_Random.h"
|
||||
|
||||
class StringTests : public UnitTest
|
||||
{
|
||||
public:
|
||||
StringTests() : UnitTest ("String class") {}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
{
|
||||
beginTest ("Basics");
|
||||
|
||||
expect (String().length() == 0);
|
||||
expect (String() == String::empty);
|
||||
String s1, s2 ("abcd");
|
||||
expect (s1.isEmpty() && ! s1.isNotEmpty());
|
||||
expect (s2.isNotEmpty() && ! s2.isEmpty());
|
||||
expect (s2.length() == 4);
|
||||
s1 = "abcd";
|
||||
expect (s2 == s1 && s1 == s2);
|
||||
expect (s1 == "abcd" && s1 == L"abcd");
|
||||
expect (String ("abcd") == String (L"abcd"));
|
||||
expect (String ("abcdefg", 4) == L"abcd");
|
||||
expect (String ("abcdefg", 4) == String (L"abcdefg", 4));
|
||||
expect (String::charToString ('x') == "x");
|
||||
expect (String::charToString (0) == String::empty);
|
||||
expect (s2 + "e" == "abcde" && s2 + 'e' == "abcde");
|
||||
expect (s2 + L'e' == "abcde" && s2 + L"e" == "abcde");
|
||||
expect (s1.equalsIgnoreCase ("abcD") && s1 < "abce" && s1 > "abbb");
|
||||
expect (s1.startsWith ("ab") && s1.startsWith ("abcd") && ! s1.startsWith ("abcde"));
|
||||
expect (s1.startsWithIgnoreCase ("aB") && s1.endsWithIgnoreCase ("CD"));
|
||||
expect (s1.endsWith ("bcd") && ! s1.endsWith ("aabcd"));
|
||||
expect (s1.indexOf (String::empty) == 0);
|
||||
expect (s1.startsWith (String::empty) && s1.endsWith (String::empty) && s1.contains (String::empty));
|
||||
expect (s1.contains ("cd") && s1.contains ("ab") && s1.contains ("abcd"));
|
||||
expect (s1.containsChar ('a') && ! s1.containsChar (0));
|
||||
expect (String ("abc foo bar").containsWholeWord ("abc") && String ("abc foo bar").containsWholeWord ("abc"));
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("Operations");
|
||||
|
||||
String s ("012345678");
|
||||
expect (s.hashCode() != 0);
|
||||
expect (s.hashCode64() != 0);
|
||||
expect (s.hashCode() != (s + s).hashCode());
|
||||
expect (s.hashCode64() != (s + s).hashCode64());
|
||||
expect (s.compare (String ("012345678")) == 0);
|
||||
expect (s.compare (String ("012345679")) < 0);
|
||||
expect (s.compare (String ("012345676")) > 0);
|
||||
expect (s.substring (2, 3) == String::charToString (s[2]));
|
||||
expect (s.substring (0, 1) == String::charToString (s[0]));
|
||||
expect (s.getLastCharacter() == s [s.length() - 1]);
|
||||
expect (String::charToString (s.getLastCharacter()) == s.getLastCharacters (1));
|
||||
expect (s.substring (0, 3) == L"012");
|
||||
expect (s.substring (0, 100) == s);
|
||||
expect (s.substring (-1, 100) == s);
|
||||
expect (s.substring (3) == "345678");
|
||||
expect (s.indexOf (L"45") == 4);
|
||||
expect (String ("444445").indexOf ("45") == 4);
|
||||
expect (String ("444445").lastIndexOfChar ('4') == 4);
|
||||
expect (String ("45454545x").lastIndexOf (L"45") == 6);
|
||||
expect (String ("45454545x").lastIndexOfAnyOf ("456") == 7);
|
||||
expect (String ("45454545x").lastIndexOfAnyOf (L"456x") == 8);
|
||||
expect (String ("abABaBaBa").lastIndexOfIgnoreCase ("Ab") == 6);
|
||||
expect (s.indexOfChar (L'4') == 4);
|
||||
expect (s + s == "012345678012345678");
|
||||
expect (s.startsWith (s));
|
||||
expect (s.startsWith (s.substring (0, 4)));
|
||||
expect (s.startsWith (s.dropLastCharacters (4)));
|
||||
expect (s.endsWith (s.substring (5)));
|
||||
expect (s.endsWith (s));
|
||||
expect (s.contains (s.substring (3, 6)));
|
||||
expect (s.contains (s.substring (3)));
|
||||
expect (s.startsWithChar (s[0]));
|
||||
expect (s.endsWithChar (s.getLastCharacter()));
|
||||
expect (s [s.length()] == 0);
|
||||
expect (String ("abcdEFGH").toLowerCase() == String ("abcdefgh"));
|
||||
expect (String ("abcdEFGH").toUpperCase() == String ("ABCDEFGH"));
|
||||
|
||||
String s2 ("123");
|
||||
s2 << ((int) 4) << ((short) 5) << "678" << L"9" << '0';
|
||||
s2 += "xyz";
|
||||
expect (s2 == "1234567890xyz");
|
||||
|
||||
beginTest ("Numeric conversions");
|
||||
expect (String::empty.getIntValue() == 0);
|
||||
expect (String::empty.getDoubleValue() == 0.0);
|
||||
expect (String::empty.getFloatValue() == 0.0f);
|
||||
expect (s.getIntValue() == 12345678);
|
||||
expect (s.getLargeIntValue() == (int64) 12345678);
|
||||
expect (s.getDoubleValue() == 12345678.0);
|
||||
expect (s.getFloatValue() == 12345678.0f);
|
||||
expect (String (-1234).getIntValue() == -1234);
|
||||
expect (String ((int64) -1234).getLargeIntValue() == -1234);
|
||||
expect (String (-1234.56).getDoubleValue() == -1234.56);
|
||||
expect (String (-1234.56f).getFloatValue() == -1234.56f);
|
||||
expect (("xyz" + s).getTrailingIntValue() == s.getIntValue());
|
||||
expect (s.getHexValue32() == 0x12345678);
|
||||
expect (s.getHexValue64() == (int64) 0x12345678);
|
||||
expect (String::toHexString (0x1234abcd).equalsIgnoreCase ("1234abcd"));
|
||||
expect (String::toHexString ((int64) 0x1234abcd).equalsIgnoreCase ("1234abcd"));
|
||||
expect (String::toHexString ((short) 0x12ab).equalsIgnoreCase ("12ab"));
|
||||
|
||||
unsigned char data[] = { 1, 2, 3, 4, 0xa, 0xb, 0xc, 0xd };
|
||||
expect (String::toHexString (data, 8, 0).equalsIgnoreCase ("010203040a0b0c0d"));
|
||||
expect (String::toHexString (data, 8, 1).equalsIgnoreCase ("01 02 03 04 0a 0b 0c 0d"));
|
||||
expect (String::toHexString (data, 8, 2).equalsIgnoreCase ("0102 0304 0a0b 0c0d"));
|
||||
|
||||
beginTest ("Subsections");
|
||||
String s3;
|
||||
s3 = "abcdeFGHIJ";
|
||||
expect (s3.equalsIgnoreCase ("ABCdeFGhiJ"));
|
||||
expect (s3.compareIgnoreCase (L"ABCdeFGhiJ") == 0);
|
||||
expect (s3.containsIgnoreCase (s3.substring (3)));
|
||||
expect (s3.indexOfAnyOf ("xyzf", 2, true) == 5);
|
||||
expect (s3.indexOfAnyOf (L"xyzf", 2, false) == -1);
|
||||
expect (s3.indexOfAnyOf ("xyzF", 2, false) == 5);
|
||||
expect (s3.containsAnyOf (L"zzzFs"));
|
||||
expect (s3.startsWith ("abcd"));
|
||||
expect (s3.startsWithIgnoreCase (L"abCD"));
|
||||
expect (s3.startsWith (String::empty));
|
||||
expect (s3.startsWithChar ('a'));
|
||||
expect (s3.endsWith (String ("HIJ")));
|
||||
expect (s3.endsWithIgnoreCase (L"Hij"));
|
||||
expect (s3.endsWith (String::empty));
|
||||
expect (s3.endsWithChar (L'J'));
|
||||
expect (s3.indexOf ("HIJ") == 7);
|
||||
expect (s3.indexOf (L"HIJK") == -1);
|
||||
expect (s3.indexOfIgnoreCase ("hij") == 7);
|
||||
expect (s3.indexOfIgnoreCase (L"hijk") == -1);
|
||||
|
||||
String s4 (s3);
|
||||
s4.append (String ("xyz123"), 3);
|
||||
expect (s4 == s3 + "xyz");
|
||||
|
||||
expect (String (1234) < String (1235));
|
||||
expect (String (1235) > String (1234));
|
||||
expect (String (1234) >= String (1234));
|
||||
expect (String (1234) <= String (1234));
|
||||
expect (String (1235) >= String (1234));
|
||||
expect (String (1234) <= String (1235));
|
||||
|
||||
String s5 ("word word2 word3");
|
||||
expect (s5.containsWholeWord (String ("word2")));
|
||||
expect (s5.indexOfWholeWord ("word2") == 5);
|
||||
expect (s5.containsWholeWord (L"word"));
|
||||
expect (s5.containsWholeWord ("word3"));
|
||||
expect (s5.containsWholeWord (s5));
|
||||
expect (s5.containsWholeWordIgnoreCase (L"Word2"));
|
||||
expect (s5.indexOfWholeWordIgnoreCase ("Word2") == 5);
|
||||
expect (s5.containsWholeWordIgnoreCase (L"Word"));
|
||||
expect (s5.containsWholeWordIgnoreCase ("Word3"));
|
||||
expect (! s5.containsWholeWordIgnoreCase (L"Wordx"));
|
||||
expect (!s5.containsWholeWordIgnoreCase ("xWord2"));
|
||||
expect (s5.containsNonWhitespaceChars());
|
||||
expect (! String (" \n\r\t").containsNonWhitespaceChars());
|
||||
|
||||
expect (s5.matchesWildcard (L"wor*", false));
|
||||
expect (s5.matchesWildcard ("wOr*", true));
|
||||
expect (s5.matchesWildcard (L"*word3", true));
|
||||
expect (s5.matchesWildcard ("*word?", true));
|
||||
expect (s5.matchesWildcard (L"Word*3", true));
|
||||
|
||||
expect (s5.fromFirstOccurrenceOf (String::empty, true, false) == s5);
|
||||
expect (s5.fromFirstOccurrenceOf ("xword2", true, false) == s5.substring (100));
|
||||
expect (s5.fromFirstOccurrenceOf (L"word2", true, false) == s5.substring (5));
|
||||
expect (s5.fromFirstOccurrenceOf ("Word2", true, true) == s5.substring (5));
|
||||
expect (s5.fromFirstOccurrenceOf ("word2", false, false) == s5.getLastCharacters (6));
|
||||
expect (s5.fromFirstOccurrenceOf (L"Word2", false, true) == s5.getLastCharacters (6));
|
||||
|
||||
expect (s5.fromLastOccurrenceOf (String::empty, true, false) == s5);
|
||||
expect (s5.fromLastOccurrenceOf (L"wordx", true, false) == s5);
|
||||
expect (s5.fromLastOccurrenceOf ("word", true, false) == s5.getLastCharacters (5));
|
||||
expect (s5.fromLastOccurrenceOf (L"worD", true, true) == s5.getLastCharacters (5));
|
||||
expect (s5.fromLastOccurrenceOf ("word", false, false) == s5.getLastCharacters (1));
|
||||
expect (s5.fromLastOccurrenceOf (L"worD", false, true) == s5.getLastCharacters (1));
|
||||
|
||||
expect (s5.upToFirstOccurrenceOf (String::empty, true, false).isEmpty());
|
||||
expect (s5.upToFirstOccurrenceOf ("word4", true, false) == s5);
|
||||
expect (s5.upToFirstOccurrenceOf (L"word2", true, false) == s5.substring (0, 10));
|
||||
expect (s5.upToFirstOccurrenceOf ("Word2", true, true) == s5.substring (0, 10));
|
||||
expect (s5.upToFirstOccurrenceOf (L"word2", false, false) == s5.substring (0, 5));
|
||||
expect (s5.upToFirstOccurrenceOf ("Word2", false, true) == s5.substring (0, 5));
|
||||
|
||||
expect (s5.upToLastOccurrenceOf (String::empty, true, false) == s5);
|
||||
expect (s5.upToLastOccurrenceOf ("zword", true, false) == s5);
|
||||
expect (s5.upToLastOccurrenceOf ("word", true, false) == s5.dropLastCharacters (1));
|
||||
expect (s5.dropLastCharacters(1).upToLastOccurrenceOf ("word", true, false) == s5.dropLastCharacters (1));
|
||||
expect (s5.upToLastOccurrenceOf ("Word", true, true) == s5.dropLastCharacters (1));
|
||||
expect (s5.upToLastOccurrenceOf ("word", false, false) == s5.dropLastCharacters (5));
|
||||
expect (s5.upToLastOccurrenceOf ("Word", false, true) == s5.dropLastCharacters (5));
|
||||
|
||||
expect (s5.replace ("word", L"xyz", false) == String ("xyz xyz2 xyz3"));
|
||||
expect (s5.replace (L"Word", "xyz", true) == "xyz xyz2 xyz3");
|
||||
expect (s5.dropLastCharacters (1).replace ("Word", String ("xyz"), true) == L"xyz xyz2 xyz");
|
||||
expect (s5.replace ("Word", "", true) == " 2 3");
|
||||
expect (s5.replace ("Word2", L"xyz", true) == String ("word xyz word3"));
|
||||
expect (s5.replaceCharacter (L'w', 'x') != s5);
|
||||
expect (s5.replaceCharacter ('w', L'x').replaceCharacter ('x', 'w') == s5);
|
||||
expect (s5.replaceCharacters ("wo", "xy") != s5);
|
||||
expect (s5.replaceCharacters ("wo", "xy").replaceCharacters ("xy", L"wo") == s5);
|
||||
expect (s5.retainCharacters ("1wordxya") == String ("wordwordword"));
|
||||
expect (s5.retainCharacters (String::empty).isEmpty());
|
||||
expect (s5.removeCharacters ("1wordxya") == " 2 3");
|
||||
expect (s5.removeCharacters (String::empty) == s5);
|
||||
expect (s5.initialSectionContainingOnly ("word") == L"word");
|
||||
expect (s5.initialSectionNotContaining (String ("xyz ")) == String ("word"));
|
||||
expect (! s5.isQuotedString());
|
||||
expect (s5.quoted().isQuotedString());
|
||||
expect (! s5.quoted().unquoted().isQuotedString());
|
||||
expect (! String ("x'").isQuotedString());
|
||||
expect (String ("'x").isQuotedString());
|
||||
|
||||
String s6 (" \t xyz \t\r\n");
|
||||
expect (s6.trim() == String ("xyz"));
|
||||
expect (s6.trim().trim() == "xyz");
|
||||
expect (s5.trim() == s5);
|
||||
expect (s6.trimStart().trimEnd() == s6.trim());
|
||||
expect (s6.trimStart().trimEnd() == s6.trimEnd().trimStart());
|
||||
expect (s6.trimStart().trimStart().trimEnd().trimEnd() == s6.trimEnd().trimStart());
|
||||
expect (s6.trimStart() != s6.trimEnd());
|
||||
expect (("\t\r\n " + s6 + "\t\n \r").trim() == s6.trim());
|
||||
expect (String::repeatedString ("xyz", 3) == L"xyzxyzxyz");
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("UTF8");
|
||||
|
||||
String s ("word word2 word3");
|
||||
|
||||
{
|
||||
char buffer [100];
|
||||
memset (buffer, 0xff, sizeof (buffer));
|
||||
s.copyToUTF8 (buffer, 100);
|
||||
expect (String::fromUTF8 (buffer, 100) == s);
|
||||
|
||||
juce_wchar bufferUnicode [100];
|
||||
memset (bufferUnicode, 0xff, sizeof (bufferUnicode));
|
||||
s.copyToUnicode (bufferUnicode, 100);
|
||||
expect (String (bufferUnicode, 100) == s);
|
||||
}
|
||||
|
||||
{
|
||||
juce_wchar wideBuffer [50];
|
||||
zerostruct (wideBuffer);
|
||||
|
||||
for (int i = 0; i < numElementsInArray (wideBuffer) - 1; ++i)
|
||||
wideBuffer[i] = (juce_wchar) (1 + Random::getSystemRandom().nextInt (std::numeric_limits<juce_wchar>::max() - 1));
|
||||
|
||||
String wide (wideBuffer);
|
||||
expect (wide == (const juce_wchar*) wideBuffer);
|
||||
expect (wide.length() == numElementsInArray (wideBuffer) - 1);
|
||||
expect (String::fromUTF8 (wide.toUTF8()) == wide);
|
||||
expect (String::fromUTF8 (wide.toUTF8()) == wideBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static StringTests stringUnitTests;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -193,36 +193,43 @@ public:
|
|||
int compareLexicographically (const String& other) const throw();
|
||||
|
||||
/** Tests whether the string begins with another string.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool startsWith (const String& text) const throw();
|
||||
|
||||
/** Tests whether the string begins with a particular character.
|
||||
If the character is 0, this will always return false.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool startsWithChar (juce_wchar character) const throw();
|
||||
|
||||
/** Tests whether the string begins with another string.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-insensitive comparison.
|
||||
*/
|
||||
bool startsWithIgnoreCase (const String& text) const throw();
|
||||
|
||||
/** Tests whether the string ends with another string.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool endsWith (const String& text) const throw();
|
||||
|
||||
/** Tests whether the string ends with a particular character.
|
||||
If the character is 0, this will always return false.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool endsWithChar (juce_wchar character) const throw();
|
||||
|
||||
/** Tests whether the string ends with another string.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-insensitive comparison.
|
||||
*/
|
||||
bool endsWithIgnoreCase (const String& text) const throw();
|
||||
|
||||
/** Tests whether the string contains another substring.
|
||||
If the parameter is an empty string, this will always return true.
|
||||
Uses a case-sensitive comparison.
|
||||
*/
|
||||
bool contains (const String& text) const throw();
|
||||
|
|
|
|||
207
src/utilities/juce_UnitTest.cpp
Normal file
207
src/utilities/juce_UnitTest.cpp
Normal file
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-10 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_UnitTest.h"
|
||||
#include "../threads/juce_ScopedLock.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
UnitTest::UnitTest (const String& name_)
|
||||
: name (name_), runner (0)
|
||||
{
|
||||
getAllTests().add (this);
|
||||
}
|
||||
|
||||
UnitTest::~UnitTest()
|
||||
{
|
||||
getAllTests().removeValue (this);
|
||||
}
|
||||
|
||||
Array<UnitTest*>& UnitTest::getAllTests()
|
||||
{
|
||||
static Array<UnitTest*> tests;
|
||||
return tests;
|
||||
}
|
||||
|
||||
void UnitTest::performTest (UnitTestRunner* const runner_)
|
||||
{
|
||||
jassert (runner_ != 0);
|
||||
runner = runner_;
|
||||
runTest();
|
||||
}
|
||||
|
||||
void UnitTest::logMessage (const String& message)
|
||||
{
|
||||
runner->logMessage (message);
|
||||
}
|
||||
|
||||
void UnitTest::beginTest (const String& testName)
|
||||
{
|
||||
runner->beginNewTest (this, testName);
|
||||
}
|
||||
|
||||
void UnitTest::expect (const bool result, const String& failureMessage)
|
||||
{
|
||||
if (result)
|
||||
runner->addPass();
|
||||
else
|
||||
runner->addFail (failureMessage);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
UnitTestRunner::UnitTestRunner()
|
||||
: currentTest (0), assertOnFailure (false)
|
||||
{
|
||||
}
|
||||
|
||||
UnitTestRunner::~UnitTestRunner()
|
||||
{
|
||||
}
|
||||
|
||||
void UnitTestRunner::resultsUpdated()
|
||||
{
|
||||
}
|
||||
|
||||
void UnitTestRunner::runTests (const Array<UnitTest*>& tests, const bool assertOnFailure_)
|
||||
{
|
||||
results.clear();
|
||||
assertOnFailure = assertOnFailure_;
|
||||
resultsUpdated();
|
||||
|
||||
for (int i = 0; i < tests.size(); ++i)
|
||||
{
|
||||
try
|
||||
{
|
||||
tests.getUnchecked(i)->performTest (this);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
addFail ("An unhandled exception was thrown!");
|
||||
}
|
||||
}
|
||||
|
||||
endTest();
|
||||
}
|
||||
|
||||
void UnitTestRunner::runAllTests (const bool assertOnFailure_)
|
||||
{
|
||||
runTests (UnitTest::getAllTests(), assertOnFailure_);
|
||||
}
|
||||
|
||||
void UnitTestRunner::logMessage (const String& message)
|
||||
{
|
||||
Logger::writeToLog (message);
|
||||
}
|
||||
|
||||
void UnitTestRunner::beginNewTest (UnitTest* const test, const String& subCategory)
|
||||
{
|
||||
endTest();
|
||||
currentTest = test;
|
||||
|
||||
TestResult* const r = new TestResult();
|
||||
r->unitTestName = test->getName();
|
||||
r->subcategoryName = subCategory;
|
||||
r->passes = 0;
|
||||
r->failures = 0;
|
||||
results.add (r);
|
||||
|
||||
logMessage ("-----------------------------------------------------------------");
|
||||
logMessage ("Starting test: " + r->unitTestName + " / " + subCategory + "...");
|
||||
|
||||
resultsUpdated();
|
||||
}
|
||||
|
||||
void UnitTestRunner::endTest()
|
||||
{
|
||||
if (results.size() > 0)
|
||||
{
|
||||
TestResult* const r = results.getLast();
|
||||
|
||||
if (r->failures > 0)
|
||||
{
|
||||
String m ("FAILED!!");
|
||||
m << r->failures << (r->failures == 1 ? "test" : "tests")
|
||||
<< " failed, out of a total of " << (r->passes + r->failures);
|
||||
|
||||
logMessage (String::empty);
|
||||
logMessage (m);
|
||||
logMessage (String::empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
logMessage ("All tests completed successfully");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UnitTestRunner::addPass()
|
||||
{
|
||||
{
|
||||
const ScopedLock sl (results.getLock());
|
||||
|
||||
TestResult* const r = results.getLast();
|
||||
jassert (r != 0); // You need to call UnitTest::beginTest() before performing any tests!
|
||||
|
||||
r->passes++;
|
||||
|
||||
String message ("Test ");
|
||||
message << (r->failures + r->passes) << " passed";
|
||||
logMessage (message);
|
||||
}
|
||||
|
||||
resultsUpdated();
|
||||
}
|
||||
|
||||
void UnitTestRunner::addFail (const String& failureMessage)
|
||||
{
|
||||
{
|
||||
const ScopedLock sl (results.getLock());
|
||||
|
||||
TestResult* const r = results.getLast();
|
||||
jassert (r != 0); // You need to call UnitTest::beginTest() before performing any tests!
|
||||
|
||||
r->failures++;
|
||||
|
||||
String message ("!!! Test ");
|
||||
message << (r->failures + r->passes) << " failed";
|
||||
|
||||
if (failureMessage.isNotEmpty())
|
||||
message << ": " << failureMessage;
|
||||
|
||||
r->messages.add (message);
|
||||
|
||||
logMessage (message);
|
||||
}
|
||||
|
||||
resultsUpdated();
|
||||
|
||||
if (assertOnFailure) { jassertfalse }
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
245
src/utilities/juce_UnitTest.h
Normal file
245
src/utilities/juce_UnitTest.h
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-10 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online at www.gnu.org/licenses.
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_UNITTEST_JUCEHEADER__
|
||||
#define __JUCE_UNITTEST_JUCEHEADER__
|
||||
|
||||
#include "../text/juce_StringArray.h"
|
||||
#include "../containers/juce_OwnedArray.h"
|
||||
class UnitTestRunner;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
This is a base class for classes that perform a unit test.
|
||||
|
||||
To write a test using this class, your code should look something like this:
|
||||
|
||||
@code
|
||||
class MyTest : public UnitTest
|
||||
{
|
||||
public:
|
||||
MyTest() : UnitTest ("Foobar testing") {}
|
||||
|
||||
void runTest()
|
||||
{
|
||||
beginTest ("Part 1");
|
||||
|
||||
expect (myFoobar.doesSomething());
|
||||
expect (myFoobar.doesSomethingElse());
|
||||
|
||||
beginTest ("Part 2");
|
||||
|
||||
expect (myOtherFoobar.doesSomething());
|
||||
expect (myOtherFoobar.doesSomethingElse());
|
||||
|
||||
...etc..
|
||||
}
|
||||
};
|
||||
|
||||
// Creating a static instance will automatically add the instance to the array
|
||||
// returned by UnitTest::getAllTests(), so the test will be included when you call
|
||||
// UnitTestRunner::runAllTests()
|
||||
static MyTest test;
|
||||
@endcode
|
||||
|
||||
To run a test, use the UnitTestRunner class.
|
||||
|
||||
@see UnitTestRunner
|
||||
*/
|
||||
class UnitTest
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a test with the given name. */
|
||||
UnitTest (const String& name);
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~UnitTest();
|
||||
|
||||
/** Returns the name of the test. */
|
||||
const String getName() const throw() { return name; }
|
||||
|
||||
/** Runs the test, using the specified UnitTestRunner.
|
||||
You shouldn't need to call this method directly - use
|
||||
UnitTestRunner::runTests() instead.
|
||||
*/
|
||||
void performTest (UnitTestRunner* runner);
|
||||
|
||||
/** Returns the set of all UnitTest objects that currently exist. */
|
||||
static Array<UnitTest*>& getAllTests();
|
||||
|
||||
//==============================================================================
|
||||
/** Implement this method in your subclass to actually run your tests.
|
||||
|
||||
The content of your implementation should call beginTest() and expect()
|
||||
to perform the tests.
|
||||
*/
|
||||
virtual void runTest() = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Tells the system that a new subsection of tests is beginning.
|
||||
This should be called from your runTest() method, and may be called
|
||||
as many times as you like, to demarcate different sets of tests.
|
||||
*/
|
||||
void beginTest (const String& testName);
|
||||
|
||||
//==============================================================================
|
||||
/** Checks that the result of a test is true, and logs this result.
|
||||
|
||||
In your runTest() method, you should call this method for each condition that
|
||||
you want to check, e.g.
|
||||
|
||||
@code
|
||||
void runTest()
|
||||
{
|
||||
beginTest ("basic tests");
|
||||
expect (x + y == 2);
|
||||
expect (getThing() == someThing);
|
||||
...etc...
|
||||
}
|
||||
@endcode
|
||||
|
||||
If testResult is true, a pass is logged; if it's false, a failure is logged.
|
||||
If the failure message is specified, it will be written to the log if the test fails.
|
||||
*/
|
||||
void expect (bool testResult, const String& failureMessage = String::empty);
|
||||
|
||||
//==============================================================================
|
||||
/** Writes a message to the test log.
|
||||
This can only be called from within your runTest() method.
|
||||
*/
|
||||
void logMessage (const String& message);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const String name;
|
||||
UnitTestRunner* runner;
|
||||
|
||||
UnitTest (const UnitTest&);
|
||||
UnitTest& operator= (const UnitTest&);
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Runs a set of unit tests.
|
||||
|
||||
You can instantiate one of these objects and use it to invoke tests on a set of
|
||||
UnitTest objects.
|
||||
|
||||
By using a subclass of UnitTestRunner, you can intercept logging messages and
|
||||
perform custom behaviour when each test completes.
|
||||
|
||||
@see UnitTest
|
||||
*/
|
||||
class UnitTestRunner
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** */
|
||||
UnitTestRunner();
|
||||
|
||||
/** Destructor. */
|
||||
virtual ~UnitTestRunner();
|
||||
|
||||
/** Runs a set of tests.
|
||||
|
||||
The tests are performed in order, and the results are logged. To run all the
|
||||
registered UnitTest objects that exist, use runAllTests().
|
||||
*/
|
||||
void runTests (const Array<UnitTest*>& tests, bool assertOnFailure);
|
||||
|
||||
/** Runs all the UnitTest objects that currently exist.
|
||||
This calls runTests() for all the objects listed in UnitTest::getAllTests().
|
||||
*/
|
||||
void runAllTests (bool assertOnFailure);
|
||||
|
||||
//==============================================================================
|
||||
/** Contains the results of a test.
|
||||
|
||||
One of these objects is instantiated each time UnitTest::beginTest() is called, and
|
||||
it contains details of the number of subsequent UnitTest::expect() calls that are
|
||||
made.
|
||||
*/
|
||||
struct TestResult
|
||||
{
|
||||
/** The main name of this test (i.e. the name of the UnitTest object being run). */
|
||||
String unitTestName;
|
||||
/** The name of the current subcategory (i.e. the name that was set when UnitTest::beginTest() was called). */
|
||||
String subcategoryName;
|
||||
|
||||
/** The number of UnitTest::expect() calls that succeeded. */
|
||||
int passes;
|
||||
/** The number of UnitTest::expect() calls that failed. */
|
||||
int failures;
|
||||
|
||||
/** A list of messages describing the failed tests. */
|
||||
StringArray messages;
|
||||
};
|
||||
|
||||
/** Returns the number of TestResult objects that have been performed.
|
||||
@see getResult
|
||||
*/
|
||||
int getNumResults() const throw();
|
||||
|
||||
/** Returns one of the TestResult objects that describes a test that has been run.
|
||||
@see getNumResults
|
||||
*/
|
||||
const TestResult* getResult (int index) const throw();
|
||||
|
||||
protected:
|
||||
/** Called when the list of results changes.
|
||||
You can override this to perform some sort of behaviour when results are added.
|
||||
*/
|
||||
virtual void resultsUpdated();
|
||||
|
||||
/** Logs a message about the current test progress.
|
||||
By default this just writes the message to the Logger class, but you could override
|
||||
this to do something else with the data.
|
||||
*/
|
||||
virtual void logMessage (const String& message);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
friend class UnitTest;
|
||||
|
||||
UnitTest* currentTest;
|
||||
String currentSubCategory;
|
||||
OwnedArray <TestResult, CriticalSection> results;
|
||||
bool assertOnFailure;
|
||||
|
||||
void beginNewTest (UnitTest* test, const String& subCategory);
|
||||
void endTest();
|
||||
|
||||
void addPass();
|
||||
void addFail (const String& failureMessage);
|
||||
|
||||
UnitTestRunner (const UnitTestRunner&);
|
||||
UnitTestRunner& operator= (const UnitTestRunner&);
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_UNITTEST_JUCEHEADER__
|
||||
Loading…
Add table
Add a link
Reference in a new issue