| @@ -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"> | |||
| @@ -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 }; | |||
| MIDIHDR hdr [(int) numInHeaders]; | |||
| char inData [(int) numInHeaders] [(int) inBufferSize]; | |||
| int pendingLength; | |||
| char pending [MidiConstants::midiBufferSize]; | |||
| MidiBuffer pending; | |||
| double timeStampToTime (uint32 timeStamp) | |||
| 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(); | |||
| @@ -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 | |||
| @@ -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__ | |||