Browse Source

New classes UnitTest and UnitTestRunner. Minor updates to VST wrapper. Added a dynamic buffer for win32 midi input.

tags/2021-05-28
Julian Storer 15 years ago
parent
commit
d2b3c283eb
34 changed files with 1871 additions and 481 deletions
  1. +6
    -0
      Builds/Linux/Makefile
  2. +8
    -2
      Builds/MacOSX/Juce.xcodeproj/project.pbxproj
  3. +2
    -0
      Builds/VisualStudio2005/Juce.vcproj
  4. +2
    -0
      Builds/VisualStudio2008/Juce.vcproj
  5. +2
    -0
      Builds/VisualStudio2008_DLL/Juce.vcproj
  6. +2
    -0
      Builds/VisualStudio2010/Juce.vcxproj
  7. +6
    -0
      Builds/VisualStudio2010/Juce.vcxproj.filters
  8. +8
    -2
      Builds/iPhone/Juce.xcodeproj/project.pbxproj
  9. +4
    -0
      Juce.jucer
  10. +1
    -0
      amalgamation/juce_amalgamated_template.cpp
  11. +2
    -2
      extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp
  12. +8
    -1
      extras/audio plugins/wrapper/juce_PluginHostType.h
  13. +4
    -4
      extras/juce demo/Builds/Linux/Makefile
  14. +4
    -2
      extras/juce demo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj
  15. +2
    -2
      extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj
  16. +2
    -2
      extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj
  17. +2
    -2
      extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj
  18. +4
    -2
      extras/juce demo/Builds/iPhone/Juce Demo.xcodeproj/project.pbxproj
  19. +2
    -2
      extras/juce demo/Juce Demo.jucer
  20. +640
    -227
      juce_amalgamated.cpp
  21. +223
    -2
      juce_amalgamated.h
  22. +5
    -10
      src/core/juce_FileLogger.cpp
  23. +0
    -1
      src/core/juce_FileLogger.h
  24. +103
    -123
      src/core/juce_Initialisation.cpp
  25. +1
    -1
      src/core/juce_StandardHeader.h
  26. +2
    -1
      src/io/files/juce_File.cpp
  27. +49
    -0
      src/io/streams/juce_MemoryInputStream.cpp
  28. +3
    -0
      src/juce_app_includes.h
  29. +47
    -92
      src/native/windows/juce_win32_Midi.cpp
  30. +1
    -1
      src/native/windows/juce_win32_Windowing.cpp
  31. +267
    -0
      src/text/juce_String.cpp
  32. +7
    -0
      src/text/juce_String.h
  33. +207
    -0
      src/utilities/juce_UnitTest.cpp
  34. +245
    -0
      src/utilities/juce_UnitTest.h

+ 6
- 0
Builds/Linux/Makefile View File

@@ -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)

+ 8
- 2
Builds/MacOSX/Juce.xcodeproj/project.pbxproj View File

@@ -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 ); };


+ 2
- 0
Builds/VisualStudio2005/Juce.vcproj View File

@@ -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"/>


+ 2
- 0
Builds/VisualStudio2008/Juce.vcproj View File

@@ -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"/>


+ 2
- 0
Builds/VisualStudio2008_DLL/Juce.vcproj View File

@@ -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"/>


+ 2
- 0
Builds/VisualStudio2010/Juce.vcxproj View File

@@ -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>


+ 6
- 0
Builds/VisualStudio2010/Juce.vcxproj.filters View File

@@ -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>


+ 8
- 2
Builds/iPhone/Juce.xcodeproj/project.pbxproj View File

@@ -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 ); };


+ 4
- 0
Juce.jucer View File

@@ -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"


+ 1
- 0
amalgamation/juce_amalgamated_template.cpp View File

@@ -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


+ 2
- 2
extras/audio plugins/wrapper/VST/juce_VST_Wrapper.cpp View File

@@ -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


+ 8
- 1
extras/audio plugins/wrapper/juce_PluginHostType.h View File

@@ -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;


+ 4
- 4
extras/juce demo/Builds/Linux/Makefile View File

@@ -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


+ 4
- 2
extras/juce demo/Builds/MacOSX/Juce Demo.xcodeproj/project.pbxproj View File

@@ -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;


+ 2
- 2
extras/juce demo/Builds/VisualStudio2005/Juce Demo.vcproj View File

@@ -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"


+ 2
- 2
extras/juce demo/Builds/VisualStudio2008/Juce Demo.vcproj View File

@@ -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"


+ 2
- 2
extras/juce demo/Builds/VisualStudio2010/Juce Demo.vcxproj View File

@@ -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/>


+ 4
- 2
extras/juce demo/Builds/iPhone/Juce Demo.xcodeproj/project.pbxproj View File

@@ -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;


+ 2
- 2
extras/juce demo/Juce Demo.jucer View File

@@ -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">


+ 640
- 227
juce_amalgamated.cpp
File diff suppressed because it is too large
View File


+ 223
- 2
juce_amalgamated.h View File

@@ -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


+ 5
- 10
src/core/juce_FileLogger.cpp View File

@@ -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";
}


+ 0
- 1
src/core/juce_FileLogger.h View File

@@ -100,7 +100,6 @@ public:
private:
File logFile;
CriticalSection logLock;
ScopedPointer <FileOutputStream> logStream;
void trimFileSize (int maxFileSizeBytes) const;


+ 103
- 123
src/core/juce_Initialisation.cpp View File

@@ -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

+ 1
- 1
src/core/juce_StandardHeader.h View File

@@ -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.


+ 2
- 1
src/io/files/juce_File.cpp View File

@@ -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);
}


+ 49
- 0
src/io/streams/juce_MemoryInputStream.cpp View File

@@ -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

+ 3
- 0
src/juce_app_includes.h View File

@@ -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

+ 47
- 92
src/native/windows/juce_win32_Midi.cpp View File

@@ -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();
}


+ 1
- 1
src/native/windows/juce_win32_Windowing.cpp View File

@@ -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())


+ 267
- 0
src/text/juce_String.cpp View File

@@ -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

+ 7
- 0
src/text/juce_String.h View File

@@ -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
- 0
src/utilities/juce_UnitTest.cpp View 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
- 0
src/utilities/juce_UnitTest.h View 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…
Cancel
Save