From 78c7ddf199a611f52a18ae6e3229bc3c52c72866 Mon Sep 17 00:00:00 2001 From: clay_shooter Date: Fri, 27 Jul 2007 03:28:44 +0000 Subject: [PATCH] 1761727 converted unit test programs to JUnit tests and updated the build targets --- build.xml | 51 +- docs/BuildingJacobFromSource.html | 49 +- docs/ReleaseNotes.html | 10 +- lib/junit3.8.1/junit.jar | Bin 0 -> 121070 bytes .../com/jacob/samples}/MathProj/Math.cls | 0 .../com/jacob/samples}/MathProj/MathTest.dll | Bin .../com/jacob/samples}/MathProj/MathTest.exp | Bin .../com/jacob/samples}/MathProj/MathTest.java | 2 +- .../com/jacob/samples}/MathProj/MathTest.lib | Bin .../com/jacob/samples}/MathProj/MathTest.vbp | 0 .../com/jacob/samples}/MathProj/MathTest.vbw | 0 .../com/jacob/samples}/MathProj/README.txt | 0 .../com/jacob/samples}/atl/MultiFace/Face.cpp | 0 .../com/jacob/samples}/atl/MultiFace/Face.h | 0 .../com/jacob/samples}/atl/MultiFace/Face.rgs | 0 .../samples}/atl/MultiFace/MultiFace.aps | Bin .../samples}/atl/MultiFace/MultiFace.cpp | 0 .../samples}/atl/MultiFace/MultiFace.def | 0 .../samples}/atl/MultiFace/MultiFace.dsp | 0 .../samples}/atl/MultiFace/MultiFace.dsw | 0 .../jacob/samples}/atl/MultiFace/MultiFace.h | 0 .../samples}/atl/MultiFace/MultiFace.idl | 0 .../samples}/atl/MultiFace/MultiFace.ncb | Bin .../samples}/atl/MultiFace/MultiFace.opt | Bin .../samples}/atl/MultiFace/MultiFace.plg | 0 .../jacob/samples}/atl/MultiFace/MultiFace.rc | 0 .../samples}/atl/MultiFace/MultiFace.tlb | Bin .../samples}/atl/MultiFace/MultiFace_i.c | 0 .../samples}/atl/MultiFace/MultiFace_p.c | 0 .../samples}/atl/MultiFace/MultiFaceps.def | 0 .../samples}/atl/MultiFace/MultiFaceps.mk | 0 .../jacob/samples}/atl/MultiFace/StdAfx.cpp | 0 .../com/jacob/samples}/atl/MultiFace/StdAfx.h | 0 .../jacob/samples}/atl/MultiFace/dlldata.c | 0 .../jacob/samples}/atl/MultiFace/resource.h | 0 .../com/jacob/samples}/atl/MultiFaceTest.java | 2 +- .../com/jacob/samples}/atl/readme.txt | 0 .../com/ActiveXComponentFactoryTest.java | 19 +- unittest/com/jacob/com/DateUtilitiesTest.java | 17 +- .../com/jacob/com/DispatchNullProgramId.java | 17 +- unittest/com/jacob/com/DispatchTest.java | 35 +- .../jacob/com/DispatchValidDispatchTest.java | 29 +- unittest/com/jacob/com/JacobObjectTest.java | 17 +- unittest/com/jacob/com/ROT2Test.java | 202 ++++---- unittest/com/jacob/com/ROT3Test.java | 248 +++++----- unittest/com/jacob/com/ROTTest.java | 22 +- unittest/com/jacob/com/VariantDateTest.java | 23 +- .../jacob/com/VariantSerializationTest.java | 63 --- unittest/com/jacob/com/VariantTest.java | 134 +++-- unittest/com/jacob/test/BaseTestCase.java | 159 ++++++ .../com/jacob/test/events/ExcelEventTest.java | 16 +- unittest/com/jacob/test/events/IETest.java | 26 +- .../jacob/test/events/IETestActiveXProxy.java | 21 +- .../com/jacob/test/events/WordEventTest.java | 17 +- .../jacob/test/powerpoint/PowerpointTest.java | 119 +++-- .../{sa_test.java => SafeArrayBasicTest.java} | 15 +- .../test/safearray/SafeArrayContents.java | 467 +++++++++--------- .../test/safearray/SafeArrayDispatchTest.java | 42 ++ .../test/safearray/SafeArrayReleaseTest.java | 15 +- .../test/safearray/SafeArrayViaExcel.java | 107 ++-- .../com/jacob/test/safearray/sa_dispatch.java | 42 -- .../com/jacob/test/vbscript/ScriptTest.bat | 2 - .../com/jacob/test/vbscript/ScriptTest.java | 91 ++-- .../com/jacob/test/vbscript/ScriptTest2.java | 166 +++---- .../test/vbscript/ScriptTest2ActiveX.java | 172 +++---- .../com/jacob/test/vbscript/ScriptTest3.java | 119 ++--- .../test/vbscript/ScriptTest3ActiveX.java | 116 ++--- .../test/vbscript/ScriptTestActiveX.java | 19 +- .../test/vbscript/ScriptTestErrEvents.java | 5 +- unittest/com/jacob/test/vbscript/speed.java | 18 - .../com/jacob/test/windowsmedia/WMPlayer.java | 22 +- 71 files changed, 1459 insertions(+), 1257 deletions(-) create mode 100644 lib/junit3.8.1/junit.jar rename {unittest/com/jacob/test => samples/com/jacob/samples}/MathProj/Math.cls (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/MathProj/MathTest.dll (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/MathProj/MathTest.exp (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/MathProj/MathTest.java (97%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/MathProj/MathTest.lib (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/MathProj/MathTest.vbp (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/MathProj/MathTest.vbw (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/MathProj/README.txt (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/Face.cpp (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/Face.h (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/Face.rgs (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.aps (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.cpp (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.def (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.dsp (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.dsw (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.h (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.idl (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.ncb (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.opt (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.plg (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.rc (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace.tlb (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace_i.c (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFace_p.c (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFaceps.def (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/MultiFaceps.mk (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/StdAfx.cpp (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/StdAfx.h (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/dlldata.c (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFace/resource.h (100%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/MultiFaceTest.java (97%) rename {unittest/com/jacob/test => samples/com/jacob/samples}/atl/readme.txt (100%) delete mode 100644 unittest/com/jacob/com/VariantSerializationTest.java create mode 100644 unittest/com/jacob/test/BaseTestCase.java rename unittest/com/jacob/test/safearray/{sa_test.java => SafeArrayBasicTest.java} (87%) create mode 100644 unittest/com/jacob/test/safearray/SafeArrayDispatchTest.java delete mode 100644 unittest/com/jacob/test/safearray/sa_dispatch.java delete mode 100644 unittest/com/jacob/test/vbscript/ScriptTest.bat delete mode 100644 unittest/com/jacob/test/vbscript/speed.java diff --git a/build.xml b/build.xml index 1e6e16f..b7106e2 100644 --- a/build.xml +++ b/build.xml @@ -5,7 +5,7 @@ Created Feb 4, 2005 1:23:05 PM as part of migration from ANT Last Modified March 24, 2007 - Tested on Eclipse 3.2 with the Callisto plugis, Ant 1.6.1 and MS Visual C++ 8 (2005) + Tested on Eclipse 3.3 with the Europa C++ plugins, Ant 1.7 and MS Visual C++ 8 (2005) Eclipse users are pretty lucky because the whole project can be built inside eclipse due to their built in ANT support. @@ -55,6 +55,8 @@ + + @@ -206,12 +208,24 @@ - Building Jacob , sample and, test classes in ${release.dir.java} - Building Jacob classes in ${release.dir.java} + + Building sample classes in ${release.dir.java} + + Building Jacob test classes in ${release.dir.java} using junit jar ${junit.jar} + - + @@ -436,5 +450,34 @@ + + + + + + + + + + + + + + + + + + + diff --git a/docs/BuildingJacobFromSource.html b/docs/BuildingJacobFromSource.html index 2160cd3..f5004a5 100644 --- a/docs/BuildingJacobFromSource.html +++ b/docs/BuildingJacobFromSource.html @@ -17,28 +17,47 @@ Unpack the source archive zip file or check the files out of CVS into d:\jacob or some other familiar place. Source Java and JNI files are located in seperate packages from the unit tests and the samples.

-The java code is in .\src.
-The C++ code is in .\jni.
-Code is compiled into .\release
+

    +
  • docs: documentation +
  • jni: c++ code +
  • lib: libraries needed to compile unit tests +
  • release: a directory built by the ant script where jacob is constructed +
  • samples: sample programs +
  • src: Jacob Java source files +
  • unittest: JUnit 3.8.1 unit test programs. Run from the test target in build.xml +
  • vstudio: some out of date VC++ project files +
  • bulid.xml: the ant build script. It can be run from inside Eclipse +

The Servlet examples that required j2ee libraries to compile have temporarily been removed.

Development Environment

The simplest build environment includes MS Visual C++ 8.0 (Studio 2005), -Eclipse 3.2 with the C/C++ module and JDK 1.4. +Eclipse 3.3 with the C/C++ module and JDK 1.4. In that situation, you would just create the compilation_tools.properties -using the example build.xml as a template. All of the releases, up through 1.12, -were built using Visual C++ 6.0. 64 bit builds are supported starting with release 1.11. -Microsoft Visual C++ 8.0 supports 64 bit builds. so no additional tools are required. - +using the example build.xml as a template.
  • Microsoft Visual C++ 8.0 and it's included library. (to D:\apps in my case) -
  • Eclipse 3.2 or later from www.eclipse.org. I use the C/C++ plugin for - eclipse rather than MS Visual Studio +
  • Eclipse 3.3 or later from www.eclipse.org as the Java IDE. +
  • Eclipse 3.3 or later with the C/C++ plugin can be used for C coding in place of VC++ IDE.
  • Java JDK 1.4 (1.12 was built using 1.4.2.13) Compilation using JDK 1.5 has not been tested

+

+ + + + + + + + + + +
ReleaseC VersionJava VersionANT VersionEclipse Version Usedgenerated DLLs
up to 1.6VC 98 (6.0)?Used MAKE?32 bit
1.7VC 98 (6.0)1.41.??32 bit
1.8VC 98 (6.0)1.41.??32 bit
1.9VC 98 (6.0)1.41.??32 bit
1.10VC 98 (6.0)1.41.?3.??32 bit
1.11VC 98 (6.0) & 2003 64bit libs1.4.?1.6.?3.2.132 and 64 bit
1.12VC 98 (6.0) & 2003 64bit libs1.4.21.6.53.2.232 and 64 bit
1.13VC 20051.4.21.7.03.332 and 64 bit
+Microsoft Visual C++ 8.0 supports 64 bit builds. so no additional tools are required. +

Build Process

@@ -85,18 +104,20 @@ Open up the project properties and go to the "Java Build Path" properties panel.
  • Add folders samples, src and unittest to the build path in the Source tab.
  • Exclude *.txt from each of the newly added folders.
  • -
  • Set the build output directory to jacob-project/release/java
  • +
  • Set the default build output directory to jacob-project/release/java
  • Running Samples and Tests

    -Samples and test programs can be found in the source jar or in CVS. The programs +Samples and JUnit test programs can be found in the source jar or in CVS. The programs can be run from a bat file or from inside the Eclipse IDE. The java library path variable must be set to include the directory the jacob.dll is in. The simplest way to do that is to add it as a command line option. +

    +JUnit test programs can be individually run from inside eclipse or en-masse +via the ant test target. - -Last Modified 4/2007 +Last Modified 7/2007 1.13M3 \ No newline at end of file diff --git a/docs/ReleaseNotes.html b/docs/ReleaseNotes.html index 4cf6664..71787a7 100644 --- a/docs/ReleaseNotes.html +++ b/docs/ReleaseNotes.html @@ -8,7 +8,10 @@ Now compiles with with Visual Studio 2005 (M1).

  • - Changed milestone release naming convetion from "pre..." to "M..." + Changed milestone release naming convention from "pre..." to "M..." +
  • +
  • + unittest directory now a JUnit 3.8.1 test repository
  • @@ -45,6 +48,11 @@ Feature Requests + + 1761727 + (M3) unittest directory test programs + converted to JUnit 3.8.1. New ANT target created to run all unit tests. +     diff --git a/lib/junit3.8.1/junit.jar b/lib/junit3.8.1/junit.jar new file mode 100644 index 0000000000000000000000000000000000000000..674d71e89ea154dbe2e3cd032821c22b39e8fd68 GIT binary patch literal 121070 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 F`9DH82$KK+ literal 0 HcmV?d00001 diff --git a/unittest/com/jacob/test/MathProj/Math.cls b/samples/com/jacob/samples/MathProj/Math.cls similarity index 100% rename from unittest/com/jacob/test/MathProj/Math.cls rename to samples/com/jacob/samples/MathProj/Math.cls diff --git a/unittest/com/jacob/test/MathProj/MathTest.dll b/samples/com/jacob/samples/MathProj/MathTest.dll similarity index 100% rename from unittest/com/jacob/test/MathProj/MathTest.dll rename to samples/com/jacob/samples/MathProj/MathTest.dll diff --git a/unittest/com/jacob/test/MathProj/MathTest.exp b/samples/com/jacob/samples/MathProj/MathTest.exp similarity index 100% rename from unittest/com/jacob/test/MathProj/MathTest.exp rename to samples/com/jacob/samples/MathProj/MathTest.exp diff --git a/unittest/com/jacob/test/MathProj/MathTest.java b/samples/com/jacob/samples/MathProj/MathTest.java similarity index 97% rename from unittest/com/jacob/test/MathProj/MathTest.java rename to samples/com/jacob/samples/MathProj/MathTest.java index 4eae736..6f9ec77 100644 --- a/unittest/com/jacob/test/MathProj/MathTest.java +++ b/samples/com/jacob/samples/MathProj/MathTest.java @@ -1,4 +1,4 @@ -package com.jacob.test.MathProj; +package com.jacob.samples.MathProj; import com.jacob.activeX.ActiveXComponent; import com.jacob.com.*; diff --git a/unittest/com/jacob/test/MathProj/MathTest.lib b/samples/com/jacob/samples/MathProj/MathTest.lib similarity index 100% rename from unittest/com/jacob/test/MathProj/MathTest.lib rename to samples/com/jacob/samples/MathProj/MathTest.lib diff --git a/unittest/com/jacob/test/MathProj/MathTest.vbp b/samples/com/jacob/samples/MathProj/MathTest.vbp similarity index 100% rename from unittest/com/jacob/test/MathProj/MathTest.vbp rename to samples/com/jacob/samples/MathProj/MathTest.vbp diff --git a/unittest/com/jacob/test/MathProj/MathTest.vbw b/samples/com/jacob/samples/MathProj/MathTest.vbw similarity index 100% rename from unittest/com/jacob/test/MathProj/MathTest.vbw rename to samples/com/jacob/samples/MathProj/MathTest.vbw diff --git a/unittest/com/jacob/test/MathProj/README.txt b/samples/com/jacob/samples/MathProj/README.txt similarity index 100% rename from unittest/com/jacob/test/MathProj/README.txt rename to samples/com/jacob/samples/MathProj/README.txt diff --git a/unittest/com/jacob/test/atl/MultiFace/Face.cpp b/samples/com/jacob/samples/atl/MultiFace/Face.cpp similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/Face.cpp rename to samples/com/jacob/samples/atl/MultiFace/Face.cpp diff --git a/unittest/com/jacob/test/atl/MultiFace/Face.h b/samples/com/jacob/samples/atl/MultiFace/Face.h similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/Face.h rename to samples/com/jacob/samples/atl/MultiFace/Face.h diff --git a/unittest/com/jacob/test/atl/MultiFace/Face.rgs b/samples/com/jacob/samples/atl/MultiFace/Face.rgs similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/Face.rgs rename to samples/com/jacob/samples/atl/MultiFace/Face.rgs diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.aps b/samples/com/jacob/samples/atl/MultiFace/MultiFace.aps similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.aps rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.aps diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.cpp b/samples/com/jacob/samples/atl/MultiFace/MultiFace.cpp similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.cpp rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.cpp diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.def b/samples/com/jacob/samples/atl/MultiFace/MultiFace.def similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.def rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.def diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.dsp b/samples/com/jacob/samples/atl/MultiFace/MultiFace.dsp similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.dsp rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.dsp diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.dsw b/samples/com/jacob/samples/atl/MultiFace/MultiFace.dsw similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.dsw rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.dsw diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.h b/samples/com/jacob/samples/atl/MultiFace/MultiFace.h similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.h rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.h diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.idl b/samples/com/jacob/samples/atl/MultiFace/MultiFace.idl similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.idl rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.idl diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.ncb b/samples/com/jacob/samples/atl/MultiFace/MultiFace.ncb similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.ncb rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.ncb diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.opt b/samples/com/jacob/samples/atl/MultiFace/MultiFace.opt similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.opt rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.opt diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.plg b/samples/com/jacob/samples/atl/MultiFace/MultiFace.plg similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.plg rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.plg diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.rc b/samples/com/jacob/samples/atl/MultiFace/MultiFace.rc similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.rc rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.rc diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace.tlb b/samples/com/jacob/samples/atl/MultiFace/MultiFace.tlb similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace.tlb rename to samples/com/jacob/samples/atl/MultiFace/MultiFace.tlb diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace_i.c b/samples/com/jacob/samples/atl/MultiFace/MultiFace_i.c similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace_i.c rename to samples/com/jacob/samples/atl/MultiFace/MultiFace_i.c diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFace_p.c b/samples/com/jacob/samples/atl/MultiFace/MultiFace_p.c similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFace_p.c rename to samples/com/jacob/samples/atl/MultiFace/MultiFace_p.c diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFaceps.def b/samples/com/jacob/samples/atl/MultiFace/MultiFaceps.def similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFaceps.def rename to samples/com/jacob/samples/atl/MultiFace/MultiFaceps.def diff --git a/unittest/com/jacob/test/atl/MultiFace/MultiFaceps.mk b/samples/com/jacob/samples/atl/MultiFace/MultiFaceps.mk similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/MultiFaceps.mk rename to samples/com/jacob/samples/atl/MultiFace/MultiFaceps.mk diff --git a/unittest/com/jacob/test/atl/MultiFace/StdAfx.cpp b/samples/com/jacob/samples/atl/MultiFace/StdAfx.cpp similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/StdAfx.cpp rename to samples/com/jacob/samples/atl/MultiFace/StdAfx.cpp diff --git a/unittest/com/jacob/test/atl/MultiFace/StdAfx.h b/samples/com/jacob/samples/atl/MultiFace/StdAfx.h similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/StdAfx.h rename to samples/com/jacob/samples/atl/MultiFace/StdAfx.h diff --git a/unittest/com/jacob/test/atl/MultiFace/dlldata.c b/samples/com/jacob/samples/atl/MultiFace/dlldata.c similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/dlldata.c rename to samples/com/jacob/samples/atl/MultiFace/dlldata.c diff --git a/unittest/com/jacob/test/atl/MultiFace/resource.h b/samples/com/jacob/samples/atl/MultiFace/resource.h similarity index 100% rename from unittest/com/jacob/test/atl/MultiFace/resource.h rename to samples/com/jacob/samples/atl/MultiFace/resource.h diff --git a/unittest/com/jacob/test/atl/MultiFaceTest.java b/samples/com/jacob/samples/atl/MultiFaceTest.java similarity index 97% rename from unittest/com/jacob/test/atl/MultiFaceTest.java rename to samples/com/jacob/samples/atl/MultiFaceTest.java index 6908ff7..862860e 100644 --- a/unittest/com/jacob/test/atl/MultiFaceTest.java +++ b/samples/com/jacob/samples/atl/MultiFaceTest.java @@ -1,4 +1,4 @@ -package com.jacob.test.atl; +package com.jacob.samples.atl; import com.jacob.com.*; import com.jacob.activeX.*; diff --git a/unittest/com/jacob/test/atl/readme.txt b/samples/com/jacob/samples/atl/readme.txt similarity index 100% rename from unittest/com/jacob/test/atl/readme.txt rename to samples/com/jacob/samples/atl/readme.txt diff --git a/unittest/com/jacob/com/ActiveXComponentFactoryTest.java b/unittest/com/jacob/com/ActiveXComponentFactoryTest.java index 2a29715..7b3c340 100644 --- a/unittest/com/jacob/com/ActiveXComponentFactoryTest.java +++ b/unittest/com/jacob/com/ActiveXComponentFactoryTest.java @@ -1,6 +1,7 @@ package com.jacob.com; import com.jacob.activeX.ActiveXComponent; +import com.jacob.test.BaseTestCase; /** * This exercises the two Dispatch factor methods that let you @@ -9,8 +10,9 @@ import com.jacob.activeX.ActiveXComponent; * May need to run with some command line options (including from inside Eclipse). * Look in the docs area at the Jacob usage document for command line options. */ -public class ActiveXComponentFactoryTest { - public static void main(String args[]) throws Exception { +public class ActiveXComponentFactoryTest extends BaseTestCase { + + public void testActiveXComponentFactory(){ ComThread.InitSTA(true); try { System.out.println("This test only works if MS Word is NOT already running"); @@ -31,26 +33,27 @@ public class ActiveXComponentFactoryTest { } ActiveXComponent mTryConnectingThird = ActiveXComponent.connectToActiveInstance(mApplicationId); if (mTryConnectingThird == null ){ - System.out.println("was unable able to connect to MSWord after previous startup"); + fail("Was unable able to connect to MSWord after previous startup"); } else { - System.out.println("Correctly could connect to running MSWord"); + System.out.println("Stopping MSWord"); // stop it so we can fail trying to connect to a running mTryConnectingThird.invoke("Quit",new Variant[] {}); - System.out.println(" Word stopped"); } Thread.sleep(2000); ActiveXComponent mTryConnectingFourth = ActiveXComponent.connectToActiveInstance(mApplicationId); if (mTryConnectingFourth != null ){ - System.out.println("Was able to connect to MSWord that was stopped"); mTryConnectingFourth.invoke("Quit",new Variant[] {}); + fail("Was able to connect to MSWord that was stopped"); } else { System.out.println("Correctly could not connect to running MSWord"); } + } catch (InterruptedException ie){ } catch (ComException e) { e.printStackTrace(); + fail("Caught COM exception"); } finally { - System.out.println("About to sleep for 2 seconds so we can bask in the glory of this success"); - Thread.sleep(2000); + //System.out.println("About to sleep for 2 seconds so we can bask in the glory of this success"); + //Thread.sleep(2000); ComThread.Release(); ComThread.quitMainSTA(); } diff --git a/unittest/com/jacob/com/DateUtilitiesTest.java b/unittest/com/jacob/com/DateUtilitiesTest.java index 0b39566..ee9792d 100644 --- a/unittest/com/jacob/com/DateUtilitiesTest.java +++ b/unittest/com/jacob/com/DateUtilitiesTest.java @@ -4,35 +4,36 @@ import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; -import com.jacob.com.DateUtilities; +import junit.framework.TestCase; /** * test cases that should exercise the new date conversion code *

    - * May need to run with some command line options (including from inside Eclipse). - * Look in the docs area at the Jacob usage document for command line options. + * This test does not require any command line options because it is only a utility test */ -public class DateUtilitiesTest { +public class DateUtilitiesTest extends TestCase { - public static void main(String[] args) - { + public void testDateUtilities(){ Date now = new Date(); double comTimeForNow = DateUtilities.convertDateToWindowsTime(now); Date retrievedNow = DateUtilities.convertWindowsTimeToDate(comTimeForNow); if (!now.equals(retrievedNow)){ - System.out.println("DateUtilities Date Test failed " +now+ " != " +retrievedNow ); + fail("DateUtilities Date Test failed " +now+ " != " +retrievedNow ); } else { System.out.println("DateUtilities Date Test passed"); } + } + + public void testBeginningOfWindowsTime(){ // this is a magic time in the windows world Date beginningOfWindowsTime = new GregorianCalendar(1899, Calendar.DECEMBER, 30).getTime(); double comTimeForBeginningOfWindowsTime = DateUtilities.convertDateToWindowsTime(beginningOfWindowsTime); if (comTimeForBeginningOfWindowsTime > 0){ - System.out.println("Beginning of windows time test failed " + fail("Beginning of windows time test failed " +comTimeForBeginningOfWindowsTime); } else { System.out.println("Beginning of windows time test passed"); diff --git a/unittest/com/jacob/com/DispatchNullProgramId.java b/unittest/com/jacob/com/DispatchNullProgramId.java index 3861b28..2df6805 100644 --- a/unittest/com/jacob/com/DispatchNullProgramId.java +++ b/unittest/com/jacob/com/DispatchNullProgramId.java @@ -1,20 +1,22 @@ package com.jacob.com; +import com.jacob.test.BaseTestCase; + /** * This test verifies that the Dispatch object protects itself when * the constructor is called with a null program id. * Prior to this protection, the VM might crash.m - * @author joe - * + *

    + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. */ -public class DispatchNullProgramId { +public class DispatchNullProgramId extends BaseTestCase { - public static void main(String[] args) { + public void testNullProgramId(){ try { String nullParam = null; new Dispatch(nullParam); - System.out.println( - "the dispatch failed to protect itself from null program ids"); + fail("the dispatch failed to protect itself from null program ids"); } catch (IllegalArgumentException iae){ System.out.println( "the dispatch protected itself from null program ids"); @@ -22,8 +24,7 @@ public class DispatchNullProgramId { try { String nullParam = ""; new Dispatch(nullParam); - System.out.println( - "the dispatch failed to protect itself from empty string program ids"); + fail("the dispatch failed to protect itself from empty string program ids"); } catch (IllegalArgumentException iae){ System.out.println( "the dispatch protected itself from empty string program ids"); diff --git a/unittest/com/jacob/com/DispatchTest.java b/unittest/com/jacob/com/DispatchTest.java index 76540f5..3b2f4b5 100644 --- a/unittest/com/jacob/com/DispatchTest.java +++ b/unittest/com/jacob/com/DispatchTest.java @@ -2,30 +2,23 @@ package com.jacob.com; import java.util.Date; -/** - * Test some of the Dispatch utility methods - * May need to run with some command line options (including from inside Eclipse). - * If so, then try these - *

    - *      -Djava.library.path=d:/jacob/release/x86 
    - *      -Dcom.jacob.autogc=false 
    - *      -Dcom.jacob.debug=false 
    - *      -Xcheck:jni
    - *  
    - */ -public class DispatchTest { +import com.jacob.test.BaseTestCase; - public static void main(String[] args) - { +/** + * Test some of the Dispatch utility methods + *

    + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. + */ +public class DispatchTest extends BaseTestCase { + + public void testDispatch() { Date testDate = new Date(); Variant fromDate = Dispatch.obj2variant(testDate); Date returnedDate = fromDate.getJavaDate(); - System.out.println("test date is "+testDate); - System.out.println("VariantDate is "+fromDate.getJavaDate()); - if (testDate.equals(returnedDate)){ - - } else { - System.out.println("Could not call obj2variant(Date) and get it to work"); - } + //System.out.println("test date is "+testDate); + //System.out.println("VariantDate is "+fromDate.getJavaDate()); + assertTrue("Could not call obj2variant(Date) and get it to work", + testDate.equals(returnedDate)); } } diff --git a/unittest/com/jacob/com/DispatchValidDispatchTest.java b/unittest/com/jacob/com/DispatchValidDispatchTest.java index b1962a2..6f37ec4 100644 --- a/unittest/com/jacob/com/DispatchValidDispatchTest.java +++ b/unittest/com/jacob/com/DispatchValidDispatchTest.java @@ -1,29 +1,28 @@ package com.jacob.com; -/** - * Test armoring of dispatch static methods - * May need to run with some command line options (including from inside Eclipse). - * If so, then try these - *

    - *      -Djava.library.path=d:/jacob/release/x86 
    - *      -Dcom.jacob.autogc=false 
    - *      -Dcom.jacob.debug=false 
    - *      -Xcheck:jni
    - *  
    - */ -public class DispatchValidDispatchTest { +import com.jacob.test.BaseTestCase; - public static void main(String[] args) - { +/** + * Test armoring of dispatch static methods + *

    + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. + */ +public class DispatchValidDispatchTest extends BaseTestCase { + + public void testThrowIllegalArgumentException() { try { Dispatch.call(null, 0); - System.out.println("Failed to throw IllegalArgumentException"); + fail("Failed to throw IllegalArgumentException"); } catch (IllegalArgumentException iae){ System.out.println("Caught correct IllegalArgumentException: "+iae); } + } + public void testThrowIllegalStateException() { try { Dispatch foo = new Dispatch(); Dispatch.call(foo, 0); + fail("Failed to throw IllegalStateException"); } catch (IllegalStateException ise){ System.out.println("Caught correct IllegalStateException "+ise); } diff --git a/unittest/com/jacob/com/JacobObjectTest.java b/unittest/com/jacob/com/JacobObjectTest.java index 443fa7a..60ead35 100644 --- a/unittest/com/jacob/com/JacobObjectTest.java +++ b/unittest/com/jacob/com/JacobObjectTest.java @@ -1,24 +1,15 @@ package com.jacob.com; +import com.jacob.test.BaseTestCase; + /** * This will eventually be changed to a unit test. *

    * May need to run with some command line options (including from inside Eclipse). - * If so, then try these - *

    - *      -Djava.library.path=d:/jacob/release/x86 
    - *      -Dcom.jacob.autogc=false 
    - *      -Dcom.jacob.debug=false 
    - *      -Xcheck:jni
    - *  
    + * Look in the docs area at the Jacob usage document for command line options. */ -public class JacobObjectTest { +public class JacobObjectTest extends BaseTestCase { - public static void main(String args[]) throws Exception - { - JacobObjectTest testJig = new JacobObjectTest(); - testJig.testBuildVersion(); - } public void testBuildVersion(){ System.out.println("build version is "+JacobObject.getBuildVersion()); diff --git a/unittest/com/jacob/com/ROT2Test.java b/unittest/com/jacob/com/ROT2Test.java index 47f4e78..fb0d6ab 100644 --- a/unittest/com/jacob/com/ROT2Test.java +++ b/unittest/com/jacob/com/ROT2Test.java @@ -1,121 +1,117 @@ package com.jacob.com; +import com.jacob.test.BaseTestCase; + /** * This test class exists to test the WeakRefernce implementation . * * It is not useful if there isn't one at this time * - * This will eventually be changed to a unit test. - * *

    - * May need to run with some command line options (including from inside Eclipse). - * Look in the docs area at the Jacob usage document for command line options. + * May need to run with some command line options (including from inside + * Eclipse). Look in the docs area at the Jacob usage document for command line + * options. */ -public class ROT2Test -{ +public class ROT2Test extends BaseTestCase { - public static void main(String args[]) throws Exception - { - ROT2TestThread threads[] = new ROT2TestThread[4]; - for (int i = 0; i < threads.length; i++) - { - threads[i] = new ROT2TestThread("thread-" + i, 3000); - } - for (int i = 0; i < threads.length; i++) - { - threads[i].start(); - } - } -} + public void testDoesNotBlowUp() { + ROT2TestThread threads[] = new ROT2TestThread[4]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new ROT2TestThread("thread-" + i, 3000); + } + for (int i = 0; i < threads.length; i++) { + threads[i].start(); + } + } -/** - * This wil try and exercise the thread support in the ROT - **/ + /** + * This will try and exercise the thread support in the ROT + */ -class ROT2TestThread extends Thread -{ - private java.util.List ThreadObjects; + public class ROT2TestThread extends Thread { + private java.util.List ThreadObjects; - private int initialRunSize = 0; - /** - * @param arg0 - */ - public ROT2TestThread(String arg0, int iStartCount) - { - super(arg0); - initialRunSize = iStartCount; - - } + private int initialRunSize = 0; - /** - * A semi-complexe serie of steps to put the ROT under stress. 1) discard - * half the objects we've created 2) if size is greater than 1 but not a - * even number, add 1 new object 3) stop when size is 1. - * - * @see java.lang.Runnable#run() - */ - public void run() - { - // something that keeps object references around - // so the gc can't collect them - // we need to create these in the thread so they end up in the right ROT table - ThreadObjects = new java.util.ArrayList(initialRunSize); - for (int i = 0; i < initialRunSize; i++) - { - // create the object - Variant aNewVariant = new Variant(getName() + "_" + i); - // create a hard reference to it - ThreadObjects.add(aNewVariant); - } + /** + * @param arg0 + */ + public ROT2TestThread(String arg0, int iStartCount) { + super(arg0); + initialRunSize = iStartCount; - while (ThreadObjects.size() > 1) - { - String message = ""; - message = getName()+" Workingset=" +ThreadObjects.size() - +" ROT: "; - message += "(before additions and gc "+ROT.getThreadObjects(false).size()+")"; - // if there is an odd number of objects greater than 2 - if (ThreadObjects.size() > 2 && ThreadObjects.size() % 2 != 0) - { - // add a new object - Variant aNewVariant = new Variant(getName() + "_*" + ThreadObjects.size()); - ThreadObjects.add(aNewVariant); - } - // now iterate across all the objects in our list - for (int i = ThreadObjects.size(); i > 0; i--) - { - // removing every other one? - if (i % 2 == 0) - { - // remove the reference so gc can get it - ThreadObjects.remove(i-1); - } + } - } - - try { - // simulate the system under load and run the GC - // should end up with weak references with no objects attached - Thread.sleep(9); - } catch (InterruptedException e){ - // the VM doesn't want us to sleep anymore, - // so get back to work - } - message += " (before gc, after additions "+ROT.getThreadObjects(false).size()+")"; - System.gc(); - message += " (after System.gc "+ROT.getThreadObjects(false).size()+")"; - System.out.println(message); - } - } + /** + * A semi-complexe serie of steps to put the ROT under stress. 1) + * discard half the objects we've created 2) if size is greater than 1 + * but not a even number, add 1 new object 3) stop when size is 1. + * + * @see java.lang.Runnable#run() + */ + public void run() { + // something that keeps object references around + // so the gc can't collect them + // we need to create these in the thread so they end up in the right + // ROT table + ThreadObjects = new java.util.ArrayList(initialRunSize); + for (int i = 0; i < initialRunSize; i++) { + // create the object + Variant aNewVariant = new Variant(getName() + "_" + i); - /** - * Another test would be to overide this to always return the same name. - * That would really screw the ROT! - * - * @see java.lang.Object#toString() - */ - public String toString() - { - return super.toString(); - } + // create a hard reference to it + ThreadObjects.add(aNewVariant); + } + + while (ThreadObjects.size() > 1) { + String message = ""; + message = getName() + " Workingset=" + ThreadObjects.size() + + " ROT: "; + message += "(before additions and gc " + + ROT.getThreadObjects(false).size() + ")"; + // if there is an odd number of objects greater than 2 + if (ThreadObjects.size() > 2 && ThreadObjects.size() % 2 != 0) { + // add a new object + Variant aNewVariant = new Variant(getName() + "_*" + + ThreadObjects.size()); + ThreadObjects.add(aNewVariant); + } + // now iterate across all the objects in our list + for (int i = ThreadObjects.size(); i > 0; i--) { + // removing every other one? + if (i % 2 == 0) { + // remove the reference so gc can get it + ThreadObjects.remove(i - 1); + } + + } + + try { + // simulate the system under load and run the GC + // should end up with weak references with no objects + // attached + Thread.sleep(9); + } catch (InterruptedException e) { + // the VM doesn't want us to sleep anymore, + // so get back to work + } + message += " (before gc, after additions " + + ROT.getThreadObjects(false).size() + ")"; + System.gc(); + message += " (after System.gc " + + ROT.getThreadObjects(false).size() + ")"; + System.out.println(message); + } + } + + /** + * Another test would be to override this to always return the same name. + * That would really screw the ROT! + * + * @see java.lang.Object#toString() + */ + public String toString() { + return super.toString(); + } + } } \ No newline at end of file diff --git a/unittest/com/jacob/com/ROT3Test.java b/unittest/com/jacob/com/ROT3Test.java index e12b818..3db3566 100644 --- a/unittest/com/jacob/com/ROT3Test.java +++ b/unittest/com/jacob/com/ROT3Test.java @@ -1,134 +1,134 @@ package com.jacob.com; +import com.jacob.test.BaseTestCase; + /** - * This trys to exercise ROT's garbage collecion - * This is named this way because the build.xml - * ignores files ending in Test when building the binary zip file + * This tries to exercise ROT's garbage collection This is named this way because + * the build.xml ignores files ending in Test when building the binary zip file * * This will eventually be changed to a unit test. * *

    - * May need to run with some command line options (including from inside Eclipse). - * Look in the docs area at the Jacob usage document for command line options. + * May need to run with some command line options (including from inside + * Eclipse). Look in the docs area at the Jacob usage document for command line + * options. */ -public class ROT3Test -{ +public class ROT3Test extends BaseTestCase { - public static void main(String args[]) throws Exception - { - ROT3TestThread threads[] = new ROT3TestThread[4]; - for (int i = 0; i < threads.length; i++) - { - threads[i] = new ROT3TestThread("thread-" + i, 3000+i*10); - } - for (int i = 0; i < threads.length; i++) - { - threads[i].start(); - } - } + public void testROTVersion3() { + ROT3TestThread threads[] = new ROT3TestThread[4]; + for (int i = 0; i < threads.length; i++) { + threads[i] = new ROT3TestThread("thread-" + i, 3000 + i * 10); + } + for (int i = 0; i < threads.length; i++) { + threads[i].start(); + } + } + + /** + * This will try and exercise the thread support in the ROT + */ + + public class ROT3TestThread extends Thread { + private java.util.List variansCreatedInThisThread; + + private int initialRunSize = 0; + + /** + * @param arg0 + */ + public ROT3TestThread(String arg0, int iStartCount) { + super(arg0); + initialRunSize = iStartCount; + + } + + /** + * A semi-complexe serie of steps to put the ROT under stress. 1) + * discard half the objects we've created 2) if size is greater than 1 + * but not a even number, add 1 new object 3) stop when size is 1. + * + * @see java.lang.Runnable#run() + */ + public void run() { + // something that keeps object references around + // so the gc can't collect them + // we need to create these in the thread so they end up in the right + // ROT table + variansCreatedInThisThread = new java.util.ArrayList(initialRunSize); + for (int i = 0; i < initialRunSize; i++) { + // create the object + Variant aNewVariant = new Variant(getName() + "_" + i); + // create a hard reference to it + variansCreatedInThisThread.add(aNewVariant); + } + + while (variansCreatedInThisThread.size() > 1) { + String message = ""; + message = getName() + " Workingset=" + + variansCreatedInThisThread.size() + + " ROT threadObject hashCode: " + + ROT.getThreadObjects(true).hashCode(); + message += " size before mods and gc " + + ROT.getThreadObjects(true).size() + ")"; + // If there are more than 10 objects in our cache then add 1/4 + // of that again + if (variansCreatedInThisThread.size() > 10) { + message += " (adding) "; + // add an additional 1/4 of our current number + for (int i = 0; i < variansCreatedInThisThread.size() / 4; i++) { + // add a new object + Variant aNewVariant = new Variant(getName() + "_*" + + variansCreatedInThisThread.size()); + variansCreatedInThisThread.add(aNewVariant); + } + } + // now iterate across 1/2 the objects in our list + message += " (removing) "; + for (int i = variansCreatedInThisThread.size(); i > 0; i--) { + // removing every other one? + if (i % 2 == 0) { + // remove the reference so gc can get it + if (!ROT.USE_AUTOMATIC_GARBAGE_COLLECTION) { + // uses deprecated API to set up a special situation + // because this is an ROT test + ROT + .removeObject((JacobObject) variansCreatedInThisThread + .get(i - 1)); + } + variansCreatedInThisThread.remove(i - 1); + } + + } + + message += " (after mods " + ROT.getThreadObjects(true).size() + + ")"; + // comm + if (!ROT.USE_AUTOMATIC_GARBAGE_COLLECTION) { + ROT.clearObjects(); + } + System.gc(); + try { + // vain attempt at letting the gc run + Thread.sleep(200); + } catch (InterruptedException ie) { + + } + message += " (after gc " + ROT.getThreadObjects(true).size() + + ")"; + message += " Should see GC if debug turned on..."; + System.out.println(message); + } + } + + /** + * Another test would be to overide this to always return the same name. + * That would really screw the ROT! + * + * @see java.lang.Object#toString() + */ + public String toString() { + return super.toString(); + } + } } - -/** - * This wil try and exercise the thread support in the ROT - **/ - -class ROT3TestThread extends Thread -{ - private java.util.List variansCreatedInThisThread; - - private int initialRunSize = 0; - /** - * @param arg0 - */ - public ROT3TestThread(String arg0, int iStartCount) - { - super(arg0); - initialRunSize = iStartCount; - - } - - /** - * A semi-complexe serie of steps to put the ROT under stress. 1) discard - * half the objects we've created 2) if size is greater than 1 but not a - * even number, add 1 new object 3) stop when size is 1. - * - * @see java.lang.Runnable#run() - */ - public void run() - { - // something that keeps object references around - // so the gc can't collect them - // we need to create these in the thread so they end up in the right ROT table - variansCreatedInThisThread = new java.util.ArrayList(initialRunSize); - for (int i = 0; i < initialRunSize; i++) - { - // create the object - Variant aNewVariant = new Variant(getName() + "_" + i); - // create a hard reference to it - variansCreatedInThisThread.add(aNewVariant); - } - - while (variansCreatedInThisThread.size() > 1) - { - String message = ""; - message = getName()+" Workingset=" +variansCreatedInThisThread.size() - +" ROT threadObject hashCode: "+ROT.getThreadObjects(true).hashCode(); - message += " size before mods and gc "+ROT.getThreadObjects(true).size()+")"; - // If there are more than 10 objects in our cache then add 1/4 of that again - if (variansCreatedInThisThread.size() > 10) - { - message+= " (adding) "; - // add an additional 1/4 of our current number - for ( int i = 0 ; i < variansCreatedInThisThread.size()/4 ; i++){ - // add a new object - Variant aNewVariant = new Variant(getName() + "_*" + variansCreatedInThisThread.size()); - variansCreatedInThisThread.add(aNewVariant); - } - } - // now iterate across 1/2 the objects in our list - message += " (removing) "; - for (int i = variansCreatedInThisThread.size(); i > 0; i--) - { - // removing every other one? - if (i % 2 == 0) - { - // remove the reference so gc can get it - if (!ROT.USE_AUTOMATIC_GARBAGE_COLLECTION){ - // uses deprecated API to set up a special situation - // because this is an ROT test - ROT.removeObject((JacobObject)variansCreatedInThisThread.get(i-1)); - } - variansCreatedInThisThread.remove(i-1); - } - - } - - message += " (after mods "+ROT.getThreadObjects(true).size()+")"; - // comm - if (!ROT.USE_AUTOMATIC_GARBAGE_COLLECTION){ - ROT.clearObjects(); - } - System.gc(); - try { - // vain attempt at letting the gc run - Thread.sleep(200); - } catch (InterruptedException ie){ - - } - message += " (after gc "+ROT.getThreadObjects(true).size()+")"; - message += " Should see GC if debug turned on..."; - System.out.println(message); - } - } - - /** - * Another test would be to overide this to always return the same name. - * That would really screw the ROT! - * - * @see java.lang.Object#toString() - */ - public String toString() - { - return super.toString(); - } -} \ No newline at end of file diff --git a/unittest/com/jacob/com/ROTTest.java b/unittest/com/jacob/com/ROTTest.java index 41694a2..dff211d 100644 --- a/unittest/com/jacob/com/ROTTest.java +++ b/unittest/com/jacob/com/ROTTest.java @@ -1,28 +1,16 @@ package com.jacob.com; -import com.jacob.com.ROT; +import com.jacob.test.BaseTestCase; /** - * This trys to exercise ROT's garbage collecion + * This tries to exercise ROT's garbage collection * * This will eventually be changed to a unit test. *

    * May need to run with some command line options (including from inside Eclipse). - * If so, then try these - *

    - *      -Djava.library.path=d:/jacob/release/x86 
    - *      -Dcom.jacob.autogc=false 
    - *      -Dcom.jacob.debug=false 
    - *      -Xcheck:jni
    - *  
    + * Look in the docs area at the Jacob usage document for command line options. */ -public class ROTTest { +public class ROTTest extends BaseTestCase { - public static void main(String args[]) throws Exception - { - ROTTest testJig = new ROTTest(); - testJig.testDontFillROTSystemProperty(); - testJig.testGCBehavior(); - } - + /** * verify the SystemProperty (classname).PutInROT functions as expected. * A value of false means instances of the class are not put in the ROT diff --git a/unittest/com/jacob/com/VariantDateTest.java b/unittest/com/jacob/com/VariantDateTest.java index 95e1c0a..371c51b 100644 --- a/unittest/com/jacob/com/VariantDateTest.java +++ b/unittest/com/jacob/com/VariantDateTest.java @@ -2,7 +2,7 @@ package com.jacob.com; import java.util.Date; -import com.jacob.com.Variant; +import com.jacob.test.BaseTestCase; /** * test cases that should exercise the new date conversion code @@ -10,32 +10,37 @@ import com.jacob.com.Variant; * May need to run with some command line options (including from inside Eclipse). * Look in the docs area at the Jacob usage document for command line options. */ -public class VariantDateTest { +public class VariantDateTest extends BaseTestCase { - public static void main(String[] args) - { + public void testVariantDate() { Date now = new Date(); Variant holder = new Variant(); holder.putDate(now); Date retrievedNow = holder.getJavaDate(); if (!now.equals(retrievedNow)){ - System.out.println("Variant Date Test failed " +now+ " != " +retrievedNow ); + fail("Variant Date Test failed " +now+ " != " +retrievedNow ); } else { - //System.out.println("Variant Date Test passed"); + System.out.println("Variant Date Test passed"); } + } + + public void testVariantDateToJavaObject(){ + Date now = new Date(); + Variant holder = new Variant(now); for ( int i = 0; i < 30000; i++){ Variant dateVariant = new Variant(now); + Date retrievedNow = holder.getJavaDate(); retrievedNow = dateVariant.getJavaDate(); if (!now.equals(retrievedNow)){ - System.out.println("Variant Date Test (1) failed " +now+ " != " +retrievedNow ); + fail("Variant Date Test (1) failed " +now+ " != " +retrievedNow ); } else { //System.out.println("Variant Date Test (1) passed"); } // verify auto typecasting works retrievedNow = (Date)dateVariant.toJavaObject(); if (!now.equals(retrievedNow)){ - System.out.println("Variant Date Test (2) failed " +now+ " != " +retrievedNow ); + fail("Variant Date Test (2) failed " +now+ " != " +retrievedNow ); } else { //System.out.println("Variant Date Test (2) passed "+retrievedNow); } @@ -47,7 +52,7 @@ public class VariantDateTest { System.out.println("int variant returned date"); } } - System.out.print("Test finished. All tests passed if no errors before this line"); + System.out.print("Test finished. All tests passed."); } diff --git a/unittest/com/jacob/com/VariantSerializationTest.java b/unittest/com/jacob/com/VariantSerializationTest.java deleted file mode 100644 index c664dfa..0000000 --- a/unittest/com/jacob/com/VariantSerializationTest.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.jacob.com; - -import java.io.*; - -/** - * Verifies serialization works for variants. - * Variant serialization is BROKEN and has been since 1.7 - *

    - * May need to run with some command line options (including from inside Eclipse). - * Look in the docs area at the Jacob usage document for command line options. - */ -class VariantSerializationTest { - - static Variant vs1 = new Variant("hi"); - static Variant vs2 = new Variant(123.456); - - public static void main(String[] args) throws Exception { - doJustSerialization(); - compareVariantBytes(); - } - - private static void compareVariantBytes() throws Exception{ - System.out.println("compareVariantBytes"); - Variant var1 = new Variant("hello"); - Variant var2 = new Variant("hello"); - byte[] var1Bytes = var1.SerializationWriteToBytes(); - byte[] var2Bytes = var2.SerializationWriteToBytes(); - for ( int i = 0 ; i < var1Bytes.length; i++){ - if (var1Bytes[i]!=var2Bytes[i]){ - System.out.println("variant strings differ at position "+i); - return; - } - } - System.out.println("two strings return identical serialization data"); - } - - private static void doJustSerialization() throws Exception { - System.out.println("doJustSerialization"); - // same thing with serialization - FileOutputStream fos; - FileInputStream fis; - fos = new FileOutputStream("foo.ser"); - ObjectOutputStream oos = new ObjectOutputStream(fos); - oos.writeObject(vs1); - //oos.writeObject(vs2); - oos.close(); - fos.close(); - - fis = new FileInputStream("foo.ser"); - ObjectInputStream ois = new ObjectInputStream(fis); - - Variant vss1 = null; - Variant vss2 = null; - - vss1 = (Variant) ois.readObject(); - //vss2 = (Variant) ois.readObject(); - ois.close(); - fis.close(); - - System.out.println(vss1); - System.out.println(vss2); - } -} diff --git a/unittest/com/jacob/com/VariantTest.java b/unittest/com/jacob/com/VariantTest.java index d85821e..6af029e 100644 --- a/unittest/com/jacob/com/VariantTest.java +++ b/unittest/com/jacob/com/VariantTest.java @@ -2,6 +2,8 @@ package com.jacob.com; import java.util.Date; +import com.jacob.test.BaseTestCase; + /** * runs through some of the get and set methods on Variant * @@ -9,33 +11,7 @@ import java.util.Date; * May need to run with some command line options (including from inside Eclipse). * Look in the docs area at the Jacob usage document for command line options. */ -class VariantTest { - public static void main(String[] args) { - System.out.println("Testing Started"); - VariantTest testJig = new VariantTest(); - testJig.testUninitializedVariant(); - testJig.testToStringDoesNotConvert(); - testJig.testPutsAndGets(); - testJig.testSafeReleaseBoolean(); - testJig.testSafeReleaseConstant(); - testJig.testSafeReleaseString(); - testJig.testObjectIsAConstant(); - testJig.testSomeChangeVT(); - testJig.testByRefToJavaObject(); - testJig.testDispatchToJavaObject(); - System.out.println("Starting last test"); - testJig.testManyThreadedInit(); - System.out.println("Testing Complete"); - - } - - /** - * dummy constructor - * - */ - public VariantTest(){ - - } +public class VariantTest extends BaseTestCase { /** * This verifies that toJavaObject() works for all of the @@ -45,21 +21,21 @@ class VariantTest { * toJavaObject() for the regular. * */ - private void testByRefToJavaObject(){ + public void testByRefToJavaObject(){ Variant v = null; Variant vByRef = null; v = new Variant(new Float(53.3),false); vByRef = new Variant(new Float(53.3),true); if (!v.toJavaObject().equals(vByRef.toJavaObject())){ - System.out.println(v.toString() + " could not make type " + fail(v.toString() + " could not make type " + v.getvt() +" and "+ vByRef.getvt() +" java objects come out the same"); } v = new Variant(new Double(53.3),false); vByRef = new Variant(new Double(53.3),true); if (!v.toJavaObject().equals(vByRef.toJavaObject())){ - System.out.println(v.toString() + " could not make type " + fail(v.toString() + " could not make type " + v.getvt() +" and "+ vByRef.getvt() +" java objects come out the same"); } @@ -67,7 +43,7 @@ class VariantTest { v = new Variant(new Boolean(true),false); vByRef = new Variant(new Boolean(true),true); if (!v.toJavaObject().equals(vByRef.toJavaObject())){ - System.out.println(v.toString() + " could not make type " + fail(v.toString() + " could not make type " + v.getvt() +" and "+ vByRef.getvt() +" java objects come out the same"); } @@ -75,7 +51,7 @@ class VariantTest { v = new Variant(new Integer(53),false); vByRef = new Variant(new Integer(53),true); if (!v.toJavaObject().equals(vByRef.toJavaObject())){ - System.out.println(v.toString() + " could not make type " + fail(v.toString() + " could not make type " + v.getvt() +" and "+ vByRef.getvt() +" java objects come out the same"); } @@ -83,7 +59,7 @@ class VariantTest { v = new Variant(new Short((short)53),false); vByRef = new Variant(new Short((short)53),true); if (!v.toJavaObject().equals(vByRef.toJavaObject())){ - System.out.println(v.toString() + " could not make type " + fail(v.toString() + " could not make type " + v.getvt() +" and "+ vByRef.getvt() +" java objects come out the same"); } @@ -91,7 +67,7 @@ class VariantTest { v = new Variant("53.33",false); vByRef = new Variant("53.33",true); if (!v.toJavaObject().equals(vByRef.toJavaObject())){ - System.out.println(v.toString() + " could not make type " + fail(v.toString() + " could not make type " + v.getvt() +" and "+ vByRef.getvt() +" java objects come out the same"); } @@ -100,7 +76,7 @@ class VariantTest { v = new Variant(now,false); vByRef = new Variant(now,true); if (!v.toJavaObject().equals(vByRef.toJavaObject())){ - System.out.println(v.toString() + " could not make type " + fail(v.toString() + " could not make type " + v.getvt() +" and "+ vByRef.getvt() +" java objects come out the same"); } @@ -113,7 +89,7 @@ class VariantTest { * instead of getDispatch so toString() on dispatch blows up. * */ - private void testDispatchToJavaObject(){ + public void testDispatchToJavaObject(){ Variant v2 = new Variant(); v2.putNothing(); // this test fails even though the exact same code below works fine @@ -124,7 +100,7 @@ class VariantTest { * see what happens when we conver to by ref * */ - private void testSomeChangeVT(){ + public void testSomeChangeVT(){ Variant v; // the code shows e shouldn't need to use a returned Variant but the test says we do Variant vConverted; @@ -135,7 +111,7 @@ class VariantTest { modifier = Variant.VariantShort; vConverted = v.changeType(modifier); if (vConverted.getvt() != modifier){ - System.out.println("Failed to change Variant "+originalVT + fail("Failed to change Variant "+originalVT + " using mask "+modifier + " resulted in "+vConverted.getvt() ); @@ -144,7 +120,7 @@ class VariantTest { modifier = Variant.VariantString; vConverted = v.changeType(modifier); if (vConverted.getvt() != modifier){ - System.out.println("Failed to change Variant "+originalVT + fail("Failed to change Variant "+originalVT + " using mask "+modifier + " resulted in "+vConverted.getvt() ); @@ -154,7 +130,7 @@ class VariantTest { modifier = Variant.VariantByref | Variant.VariantShort; vConverted = v.changeType(modifier); if (vConverted.getvt() == modifier){ - System.out.println("Should not have been able to change Variant "+originalVT + fail("Should not have been able to change Variant "+originalVT + " using mask "+modifier + " resulted in "+vConverted.getvt() ); @@ -165,7 +141,7 @@ class VariantTest { * make sure variant with no backing store works. * */ - private void testUninitializedVariant(){ + public void testUninitializedVariant(){ Variant v; // Variants created without parameters are auto set to VariantEmpty v = new Variant(); @@ -182,7 +158,7 @@ class VariantTest { try { v.toString(); } catch (IllegalStateException ise){ - System.out.println("toString() should never throw a runtime exception"); + fail("toString() should never throw a runtime exception"); throw new RuntimeException("toString() should not blow up even with uninitialized Variant"); } @@ -193,31 +169,31 @@ class VariantTest { * * verify the toString() method does not do type conversion */ - private void testToStringDoesNotConvert(){ + public void testToStringDoesNotConvert(){ Variant v; v = new Variant(true); v.toString(); if (v.getvt() != Variant.VariantBoolean){ throw new RuntimeException("toString() converted boolean to something else"); } else { - //System.out.println("toString() correctly does not convert type"); + //fail("toString() correctly does not convert type"); } if (v.getBoolean() != true){ - System.out.println("toString() converted boolean true to "+ v.getBoolean()); + fail("toString() converted boolean true to "+ v.getBoolean()); } v = new Variant(false); v.toString(); if (v.getvt() != Variant.VariantBoolean){ throw new RuntimeException("toString() converted boolean to something else"); } else { - //System.out.println("toString() correctly does not convert type"); + //fail("toString() correctly does not convert type"); } if (v.getBoolean() != false){ - System.out.println("toString() converted boolean false to "+ v.getBoolean()); + fail("toString() converted boolean false to "+ v.getBoolean()); } } - private void testSafeReleaseBoolean(){ + public void testSafeReleaseBoolean(){ Variant v; v = new Variant(true); //System.out.println("Newly created Variant ("+ v.getBoolean()+") "+ @@ -225,7 +201,7 @@ class VariantTest { v.safeRelease(); try { v.getBoolean(); - System.out.println("IllegalStateException should have been thrown when querying safeReleased object"); + fail("IllegalStateException should have been thrown when querying safeReleased object"); throw new RuntimeException("test failed"); } catch (IllegalStateException ise){ //System.out.println("IllegalStateException correctly thrown after safeRelease"); @@ -239,7 +215,7 @@ class VariantTest { ComThread.Release(); try { v.getBoolean(); - System.out.println("IllegalStateException should have been thrown when querying ComThread.Release"); + fail("IllegalStateException should have been thrown when querying ComThread.Release"); throw new RuntimeException("test failed"); } catch (IllegalStateException ise){ //System.out.println("IllegalStateException correctly thrown after ComThread.Release"); @@ -250,11 +226,11 @@ class VariantTest { * verify the constant values aren't released with safeRelease * */ - private void testSafeReleaseConstant(){ + public void testSafeReleaseConstant(){ //System.out.println("Using Static constant Variant - should never throw access violation"); Variant.VT_TRUE.safeRelease(); if (Variant.VT_TRUE.getBoolean() != true){ - System.out.println("VT_TRUE has been broken by SafeRelease()"); + fail("VT_TRUE has been broken by SafeRelease()"); throw new RuntimeException("test failed"); } else { //System.out.println("VT_TRUE survived SafeRelease()"); @@ -268,7 +244,7 @@ class VariantTest { ComThread.Release(); if (Variant.VT_TRUE.getBoolean() != true){ - System.out.println("VT_TRUE has been broken by ComThread.Release()"); + fail("VT_TRUE has been broken by ComThread.Release()"); throw new RuntimeException("test failed"); } else { //System.out.println("VT_TRUE survived ComThread.Release()"); @@ -282,7 +258,7 @@ class VariantTest { * working after a release * */ - private void testSafeReleaseString(){ + public void testSafeReleaseString(){ String mTestString = "Guitar Hero"; Variant v = new Variant(mTestString); //System.out.println("Newly created Variant ("+ v.getString()+") "+ @@ -290,7 +266,7 @@ class VariantTest { v.safeRelease(); try { v.getString(); - System.out.println("IllegalStateException should have been thrown when querying safeReleased object"); + fail("IllegalStateException should have been thrown when querying safeReleased object"); throw new RuntimeException("test failed"); } catch (IllegalStateException ise){ //System.out.println("IllegalStateException correctly thrown after safeRelease"); @@ -304,22 +280,22 @@ class VariantTest { public void testObjectIsAConstant(){ Variant v = new Variant("d"); if (!v.objectIsAConstant(Variant.VT_FALSE)){ - System.out.println("did not recognize VT_FALSE"); + fail("did not recognize VT_FALSE"); } if (!v.objectIsAConstant(Variant.VT_TRUE)){ - System.out.println("did not recognize VT_TRUE"); + fail("did not recognize VT_TRUE"); } if (!v.objectIsAConstant(Variant.VT_MISSING)){ - System.out.println("did not recognize VT_MISSING"); + fail("did not recognize VT_MISSING"); } if (!v.objectIsAConstant(Variant.DEFAULT)){ - System.out.println("did not recognize DEFAULT"); + fail("did not recognize DEFAULT"); } if (v.objectIsAConstant(new Variant(true))){ - System.out.println("confused a boolean with VT_TRUE"); + fail("confused a boolean with VT_TRUE"); } if (v.objectIsAConstant(new Variant(false))){ - System.out.println("confused a boolean with VT_FALSE"); + fail("confused a boolean with VT_FALSE"); } @@ -329,81 +305,81 @@ class VariantTest { * tests put and get methods looking for obvious defects * */ - private void testPutsAndGets(){ + public void testPutsAndGets(){ Variant v = new Variant(); v.putInt(10); if (v.getInt() != 10){ - System.out.println("int test failed"); + fail("int test failed"); } v.putShort((short)10); if (v.getShort() != 10){ - System.out.println("short test failed"); + fail("short test failed"); } v.putByte((byte)10); if (v.getByte() != 10){ - System.out.println("int test failed"); + fail("int test failed"); } v.putFloat(10); if (v.getFloat() != 10.0){ - System.out.println("float test failed"); + fail("float test failed"); } v.putDouble(10); if (v.getDouble() != 10.0){ - System.out.println("double test failed"); + fail("double test failed"); } v.putString("1234.567"); if (!"1234.567".equals(v.getString())){ - System.out.println("string test failed"); + fail("string test failed"); } v.putBoolean(true); if (v.getBoolean() != true){ - System.out.println("failed boolean test(true)"); + fail("failed boolean test(true)"); } v.putBoolean(false); if (v.getBoolean() != false){ - System.out.println("failed boolean test(false)"); + fail("failed boolean test(false)"); } v.putCurrency(123456789123456789L); if (v.getCurrency()!=123456789123456789L){ - System.out.println("failed currency test"); + fail("failed currency test"); } Date ourDate = new Date(); v.putDate(ourDate); Date retrievedDate = v.getJavaDate(); if (!retrievedDate.equals(ourDate)){ - System.out.println("failed java date load and unload"); + fail("failed java date load and unload"); } v.putNull(); if (!v.isNull()){ - System.out.println("failed detecting set null"); + fail("failed detecting set null"); } v.putString("something other than null"); if (v.isNull()){ - System.out.println("failed null replacement with string"); + fail("failed null replacement with string"); } v.putEmpty(); if (!v.isNull()){ - System.out.println("failed detecting set empty as null"); + fail("failed detecting set empty as null"); } v.putString("something other than null"); if (v.isNull()){ - System.out.println("failed empty replacement with string as isNull"); + fail("failed empty replacement with string as isNull"); } Variant v2 = new Variant(); v2.putNothing(); if (v2.getvt() != Variant.VariantDispatch){ - System.out.println("putNothing was supposed to set the type to VariantDispatch"); + fail("putNothing was supposed to set the type to VariantDispatch"); } if (!v2.isNull()){ - System.out.println("putNothing is supposed to cause isNull() to return true"); + fail("putNothing is supposed to cause isNull() to return true"); } // this line blows up in the test above if (v2.toJavaObject() == null){ - System.out.println("putNothing() followed by toJavaObject() should return a Dispatch"); + fail("putNothing() followed by toJavaObject() should return a Dispatch"); } } diff --git a/unittest/com/jacob/test/BaseTestCase.java b/unittest/com/jacob/test/BaseTestCase.java new file mode 100644 index 0000000..60823ea --- /dev/null +++ b/unittest/com/jacob/test/BaseTestCase.java @@ -0,0 +1,159 @@ +package com.jacob.test; + +import java.net.URL; + +import junit.framework.TestCase; + +import com.jacob.com.JacobObject; + +/** + * May need to run with some command line options (including from inside + * Eclipse). Look in the docs area at the Jacob usage document for command line + * options. Or try these: + * + *

    + *      -Djava.library.path=d:/jacob/release/x86 
    + *      -Dcom.jacob.autogc=false 
    + *      -Dcom.jacob.debug=false 
    + *      -Xcheck:jni
    + * 
    + */ +public class BaseTestCase extends TestCase { + + protected void setUp() { + // verify we have run with the dll in the lib path + try { + JacobObject foo = new JacobObject(); + if (foo == null) { + fail("Failed basic sanity test: Can't create JacobObject (-D)"); + } + } catch (UnsatisfiedLinkError ule) { + fail("Did you remember to run with the jacob.dll in the libpath ?"); + } + } + + /** + * this test exists just to test the setup. + */ + public void testSetup(){ + JacobObject foo = new JacobObject(); + assertNotNull(foo); + } + /** + * + * @return a simple VB script that generates the result "3" + */ + public String getSampleVPScriptForEval() { + return "1+(2*4)-3"; + + } + + /** + * Converts the class name into a path and appends the resource name. + * Used to derive the path to a resouce in the file system + * where the resource is co-located with the referenced class. + * + * @param resourceName + * @param classInSamePackageAsResource + * @return a class loader compatible fully qualified file system path to a resource + */ + public String getJavaFilePathToPackageResource(String resourceName, + Class classInSamePackageAsResource) { + + String classPackageName = classInSamePackageAsResource.getName(); + int i = classPackageName.lastIndexOf('.'); + if (i == -1) { + classPackageName = ""; + } else { + classPackageName = classPackageName.substring(0,i); + } + + // change all "." to ^ for later conversion to "/" so we can append resource names with "." + classPackageName = classPackageName.replace('.', '^'); + System.out.println("classPackageName:" + classPackageName); + + String fullPathToResource = (classPackageName.length() > 0 ? classPackageName + + "^" + : "") + + resourceName; + + fullPathToResource = fullPathToResource.replace('^', '/'); + System.out.println("fullPathToResource:" + fullPathToResource); + + URL urlToLibrary = + classInSamePackageAsResource.getClassLoader().getResource(fullPathToResource); + assertNotNull(urlToLibrary); + String fullPathToResourceAsFile = urlToLibrary.getFile(); + System.out.println("url to library: "+urlToLibrary); + System.out.println("fullPathToResourceAsFile: "+fullPathToResourceAsFile); + + return fullPathToResourceAsFile; + } + + /** + * Converts the class name into a path and appends the resource name. + * Used to derive the path to a resouce in the file system + * where the resource is co-located with the referenced class. + * + * @param resourceName + * @param classInSamePackageAsResource + * @return returns the path in the file system of the requested resource in windows c + * compatible format + */ + public String getWindowsFilePathToPackageResource( + String resourceName, Class classInSamePackageAsResource) { + String javaFilePath = getJavaFilePathToPackageResource( + resourceName, classInSamePackageAsResource); + javaFilePath = javaFilePath.replace('/', '\\'); + return javaFilePath.substring(1); + } + + /** + * + * @param resourceName + * @param classInSamePackageAsResource + * @return a resource located in the same package as the passed in class + */ + public Object getPackageResource(String resourceName, + Class classInSamePackageAsResource) { + String fullPathToResource = getJavaFilePathToPackageResource(resourceName, + classInSamePackageAsResource); + ClassLoader localClassLoader = classInSamePackageAsResource + .getClassLoader(); + if (null == localClassLoader) { + return ClassLoader.getSystemResource(fullPathToResource); + } else { + return localClassLoader.getResource(fullPathToResource); + } + } + + /** + * load a library from same place in the file system that the class was + * loaded from. + *

    + * This is an attempt to let unit tests run without having to run + * regsvr32. + * + * @param libraryName + * @param classInSamePackageAsResource + */ + public void loadLibraryFromClassPackage(String libraryName, + Class classInSamePackageAsResource) { + String libraryNameWithSuffix = ""; + String fullLibraryNameWithPath = ""; + if (libraryName != null && libraryName.endsWith("dll")) { + libraryNameWithSuffix = libraryName; + } else if (libraryName != null) { + libraryNameWithSuffix = libraryName + ".dll"; + } else { + fail("can't create full library name " + libraryName); + } + // generate the path the classloader would use to find this on the classpath + fullLibraryNameWithPath = getJavaFilePathToPackageResource( + libraryNameWithSuffix, classInSamePackageAsResource); + System.load(fullLibraryNameWithPath); + // requires that the dll be on the library path + //System.loadLibrary(fullLibraryNameWithPath); + } + +} diff --git a/unittest/com/jacob/test/events/ExcelEventTest.java b/unittest/com/jacob/test/events/ExcelEventTest.java index d1ce34b..24fcd10 100644 --- a/unittest/com/jacob/test/events/ExcelEventTest.java +++ b/unittest/com/jacob/test/events/ExcelEventTest.java @@ -6,6 +6,7 @@ import com.jacob.com.Dispatch; import com.jacob.com.DispatchEvents; import com.jacob.com.InvocationProxy; import com.jacob.com.Variant; +import com.jacob.test.BaseTestCase; /** * This test was lifted from a forum posting and shows how you can't listen to @@ -15,13 +16,13 @@ import com.jacob.com.Variant; * May need to run with some command line options (including from inside Eclipse). * Look in the docs area at the Jacob usage document for command line options. */ -public class ExcelEventTest extends InvocationProxy { +public class ExcelEventTest extends BaseTestCase { /** * load up excel, register for events and make stuff happen * @param args */ - public static void main(String args[]) { + public void testExcelWithInvocationProxy() { String pid = "Excel.Application"; String typeLibLocation = "C:\\Program Files\\Microsoft Office\\OFFICE11\\EXCEL.EXE"; @@ -31,9 +32,9 @@ public class ExcelEventTest extends InvocationProxy { // Add a listener (doesn't matter what it is). DispatchEvents de; if (typeLibLocation == null) { - de = new DispatchEvents(axc, new ExcelEventTest()); + de = new DispatchEvents(axc, new ExcelEvents()); } else { - de = new DispatchEvents(axc, new ExcelEventTest(), pid, + de = new DispatchEvents(axc, new ExcelEvents(), pid, typeLibLocation); } if (de == null) { @@ -67,16 +68,18 @@ public class ExcelEventTest extends InvocationProxy { } catch (ComException cfe) { cfe.printStackTrace(); - System.out.println("Failed to attach to " + pid + ": " + fail("Failed to attach to " + pid + ": " + cfe.getMessage()); } } + +public class ExcelEvents extends InvocationProxy { /** * Constructor so we can create an instance that implements invoke() */ - public ExcelEventTest() { + public ExcelEvents() { } /** @@ -89,3 +92,4 @@ public class ExcelEventTest extends InvocationProxy { } } +} diff --git a/unittest/com/jacob/test/events/IETest.java b/unittest/com/jacob/test/events/IETest.java index 15fdffd..cf564e0 100644 --- a/unittest/com/jacob/test/events/IETest.java +++ b/unittest/com/jacob/test/events/IETest.java @@ -1,7 +1,11 @@ package com.jacob.test.events; -import com.jacob.com.*; -import com.jacob.activeX.*; +import com.jacob.activeX.ActiveXComponent; +import com.jacob.com.ComThread; +import com.jacob.com.Dispatch; +import com.jacob.com.DispatchEvents; +import com.jacob.com.Variant; +import com.jacob.test.BaseTestCase; /** * This test runs fine against jdk 1.4 and 1.5 * @@ -15,10 +19,9 @@ import com.jacob.activeX.*; * Look in the docs area at the Jacob usage document for command line options. */ -class IETest -{ - public static void main(String[] args) - { +public class IETest extends BaseTestCase { + + public void testRunIE() { // this line starts the pump but it runs fine without it ComThread.startMainSTA(); // remove this line and it dies @@ -39,6 +42,10 @@ class IETest ComThread.quitMainSTA(); System.out.println("Main: did quit main sta in thread " +Thread.currentThread().getName()); + + if (aThread.threadFailedWithException != null){ + fail("caught an unexpected exception "+aThread.threadFailedWithException); + } } } @@ -46,6 +53,11 @@ class IETestThread extends Thread { public static boolean quitHandled = false; + /** + * holds any caught exception so the main/test case can see them + */ + public Throwable threadFailedWithException = null; + public IETestThread(){ super(); } @@ -80,8 +92,10 @@ class IETestThread extends Thread System.out.println("IETestThread: Did call navigate to yahoo"); try { Thread.sleep(delay); } catch (Exception e) {} } catch (Exception e) { + threadFailedWithException = e; e.printStackTrace(); } catch (Throwable re){ + threadFailedWithException = re; re.printStackTrace(); } finally { System.out.println("IETestThread: About to send Quit"); diff --git a/unittest/com/jacob/test/events/IETestActiveXProxy.java b/unittest/com/jacob/test/events/IETestActiveXProxy.java index 6cd90a2..7993189 100644 --- a/unittest/com/jacob/test/events/IETestActiveXProxy.java +++ b/unittest/com/jacob/test/events/IETestActiveXProxy.java @@ -5,6 +5,7 @@ import com.jacob.activeX.ActiveXDispatchEvents; import com.jacob.com.ComThread; import com.jacob.com.Dispatch; import com.jacob.com.Variant; +import com.jacob.test.BaseTestCase; /** * This test runs fine against jdk 1.4 and 1.5 * @@ -18,10 +19,10 @@ import com.jacob.com.Variant; * Look in the docs area at the Jacob usage document for command line options. */ -class IETestActiveXProxy -{ - public static void main(String[] args) - { +public class IETestActiveXProxy extends BaseTestCase { + + + public void testIEActiveProxyCallback() { // this line starts the pump but it runs fine without it ComThread.startMainSTA(); // remove this line and it dies @@ -42,6 +43,9 @@ class IETestActiveXProxy ComThread.quitMainSTA(); System.out.println("Main: did quit main sta in thread " +Thread.currentThread().getName()); + if (aThread.threadFailedWithException != null){ + fail("caught an unexpected exception "+aThread.threadFailedWithException); + } } } @@ -49,6 +53,11 @@ class IETestActiveProxyThread extends Thread { public static boolean quitHandled = false; + /** + * holds any caught exception so the main/test case can see them + */ + public Throwable threadFailedWithException = null; + public IETestActiveProxyThread(){ super(); } @@ -83,8 +92,10 @@ class IETestActiveProxyThread extends Thread System.out.println("IETestActiveProxyThread: Did call navigate to yahoo"); try { Thread.sleep(delay); } catch (Exception e) {} } catch (Exception e) { - e.printStackTrace(); + threadFailedWithException = e; + e.printStackTrace(); } catch (Throwable re){ + threadFailedWithException = re; re.printStackTrace(); } finally { System.out.println("IETestActiveProxyThread: About to send Quit"); diff --git a/unittest/com/jacob/test/events/WordEventTest.java b/unittest/com/jacob/test/events/WordEventTest.java index c6bb634..84f82c1 100644 --- a/unittest/com/jacob/test/events/WordEventTest.java +++ b/unittest/com/jacob/test/events/WordEventTest.java @@ -5,6 +5,7 @@ import com.jacob.com.ComException; import com.jacob.com.DispatchEvents; import com.jacob.com.InvocationProxy; import com.jacob.com.Variant; +import com.jacob.test.BaseTestCase; /** * This test was lifted from a forum posting and shows how you can't listen to @@ -17,13 +18,13 @@ import com.jacob.com.Variant; * May need to run with some command line options (including from inside Eclipse). * Look in the docs area at the Jacob usage document for command line options. */ -public class WordEventTest extends InvocationProxy { +public class WordEventTest extends BaseTestCase { /** * load up word, register for events and make stuff happen * @param args */ - public static void main(String args[]) { + public void testCaptureWordEvents() { String pid = "Word.Application"; String typeLibLocation = null; @@ -39,8 +40,7 @@ public class WordEventTest extends InvocationProxy { typeLibLocation); } if (de == null) { - System.out - .println("No exception thrown but no dispatch returned for Word events"); + fail("No exception thrown but no dispatch returned for Word events"); } else { // Yea! System.out.println("Successfully attached to " + pid); @@ -52,14 +52,13 @@ public class WordEventTest extends InvocationProxy { axc.setProperty("Visible",true); ActiveXComponent documents = axc.getPropertyAsComponent("Documents"); if (documents == null){ - System.out.println("unable to get documents"); + fail("unable to get documents"); } axc.invoke("Quit", new Variant[] {}); } catch (ComException cfe) { cfe.printStackTrace(); - System.out.println("Failed to attach to " + pid + ": " - + cfe.getMessage()); + fail("Failed to attach to " + pid + ": " + cfe.getMessage()); } System.out.println( @@ -68,10 +67,11 @@ public class WordEventTest extends InvocationProxy { "thinks we tested something"); } +public class WordEvents extends InvocationProxy { /** * Constructor so we can create an instance that implements invoke() */ - public WordEventTest() { + public WordEvents() { } /** @@ -83,3 +83,4 @@ public class WordEventTest extends InvocationProxy { } } +} \ No newline at end of file diff --git a/unittest/com/jacob/test/powerpoint/PowerpointTest.java b/unittest/com/jacob/test/powerpoint/PowerpointTest.java index f7cbbb2..0bb5b31 100644 --- a/unittest/com/jacob/test/powerpoint/PowerpointTest.java +++ b/unittest/com/jacob/test/powerpoint/PowerpointTest.java @@ -9,8 +9,10 @@ package com.jacob.test.powerpoint; * Look in the docs area at the Jacob usage document for command line options. */ import com.jacob.activeX.ActiveXComponent; +import com.jacob.com.ComFailException; import com.jacob.com.ComThread; import com.jacob.com.Dispatch; +import com.jacob.test.BaseTestCase; /** * @@ -18,67 +20,31 @@ import com.jacob.com.Dispatch; * The submitter stated they had the problem on windows 2000 with office 2000 * I have been unable to duplicate on windows XP with office 2003. * I am comitting this to the tree just in case we need to come back to it. + *

    + * This relies on BaseTestCase to provide the root path to the file under test + *

    + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. */ -public class PowerpointTest extends Thread { +public class PowerpointTest extends BaseTestCase { private static final int NUM_THREADS = 5; protected static final int NUM_ITERATIONS = 50; - private static String POWERPOINT_TEST_PATH = - "D:\\jacob\\samples\\com\\jacob\\test\\powerpoint"; - //"c:\\PowerpointTest\test"; - private int threadID; - private Dispatch comPowerpoint; - - public PowerpointTest(int threadID, Dispatch comPowerpoint) { - super("TestThread "+threadID); - this.threadID = threadID; - this.comPowerpoint = comPowerpoint; - } - - public void run() { - System.out.println("Thread \""+Thread.currentThread().getName()+"\" started"); - System.out.flush(); - ComThread.InitMTA(); - try { - for (int i=0; i + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. * */ -class sa_test { - public static void main(String[] args) { +public class SafeArrayBasicTest extends BaseTestCase { + public void testBasicSafeArray(){ //System.runFinalizersOnExit(true); SafeArray sa = new SafeArray(Variant.VariantVariant, 3); @@ -60,11 +65,9 @@ class sa_test { new Variant(1), new Variant(2.3), new Variant("hi") }); System.out.println("sa variant=" + sa); - sa_ND_test(); - } - public static void sa_ND_test() { + public void testSafeArrayNumDimensions() { int[] lowerBounds = new int[] { 0, 0, 0 }; int[] dimensionSizes = new int[] { 3, 3, 3 }; diff --git a/unittest/com/jacob/test/safearray/SafeArrayContents.java b/unittest/com/jacob/test/safearray/SafeArrayContents.java index 9de2ca7..b97a7c8 100644 --- a/unittest/com/jacob/test/safearray/SafeArrayContents.java +++ b/unittest/com/jacob/test/safearray/SafeArrayContents.java @@ -1,276 +1,273 @@ package com.jacob.test.safearray; -import com.jacob.com.*; +import com.jacob.com.ComFailException; +import com.jacob.com.SafeArray; +import com.jacob.com.Variant; +import com.jacob.test.BaseTestCase; -class SafeArrayContents -{ +/** + * A safe array contents test (old test) + * + *

    + * May need to run with some command line options (including from inside + * Eclipse). Look in the docs area at the Jacob usage document for command line + * options. + */ +public class SafeArrayContents extends BaseTestCase { - public static void printArray(boolean a[]) - { - System.out.print("["); - for(int i=0;i @@ -73,13 +74,15 @@ import com.jacob.com.Variant; +-----------+ | VT_ARRAY| +---------+ | parray---->SAFEARRAY| +------------+ +---------+ + * + *

    + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. */ -public class SafeArrayReleaseTest -{ +public class SafeArrayReleaseTest extends BaseTestCase { final static int MAX = 300; - public static void main(String[] args) - { + public void testSaveArrayRelease() { int count; System.out.println("Starting test for max = "+MAX); for(count = 1; count + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. + *

    + * This relies on BaseTestCase to provide the root path to the file under test + */ +public class SafeArrayViaExcel extends BaseTestCase { + public void testSafeArrayViaExcel() { + // deprecated + // System.runFinalizersOnExit(true); - ActiveXComponent xl = new ActiveXComponent("Excel.Application"); - try { - Dispatch cell; - SafeArray sAProdText; - Dispatch workbooks = xl.getProperty("Workbooks").toDispatch(); - System.out.println("have workbooks"); - Dispatch workbook = Dispatch.call(workbooks, "Open", "d:\\jacob\\samples\\test\\ExcelSafeArray" + - ".xls").toDispatch(); - System.out.println("Opened File - jacobtest.xls\n"); - Dispatch sheet = Dispatch.get(workbook,"ActiveSheet").toDispatch(); - cell = Dispatch.invoke(sheet,"Range",Dispatch.Get,new Object[] {"A1:D1000"},new int[1]).toDispatch(); - System.out.println("have cell:"+cell); - sAProdText = Dispatch.get(cell,"Value").toSafeArray(); - System.out.println("sa: dim="+sAProdText.getNumDim()); - System.out.println("sa: start row="+sAProdText.getLBound(1)); - System.out.println("sa: start col="+sAProdText.getLBound(2)); - System.out.println("sa: end row="+sAProdText.getUBound(1)); - System.out.println("sa: end col="+sAProdText.getUBound(2)); - int i; - int lineNumber=1; - int n = 0; - for(lineNumber=1; lineNumber < 1000; lineNumber++) - { - for (i = 1 ; i < 4 ; i++ ) { - System.out.println((n++) + " " + lineNumber+" "+i+" " +sAProdText.getString(lineNumber,i)); - /* - if (sAProdText.getString(lineNumber,i).compareTo("aaaa") != 0 ) { - System.out.println("Invalid String in line " + lineNumber + " Cell " + i + " Value = " + sAProdText.getString(lineNumber,i)); - stringFound = false; + ActiveXComponent xl = new ActiveXComponent("Excel.Application"); + try { + Dispatch cell; + SafeArray sAProdText; + Dispatch workbooks = xl.getProperty("Workbooks").toDispatch(); + System.out.println("have workbooks"); + Dispatch workbook = Dispatch.call( + workbooks, + "Open", + getWindowsFilePathToPackageResource("SafeArrayViaExcel.xls",this.getClass())) + .toDispatch(); + System.out.println("Opened File - SafeArrayViaExcel.xls\n"); + Dispatch sheet = Dispatch.get(workbook, "ActiveSheet").toDispatch(); + cell = Dispatch.invoke(sheet, "Range", Dispatch.Get, + new Object[] { "A1:D1000" }, new int[1]).toDispatch(); + System.out.println("have cell:" + cell); + sAProdText = Dispatch.get(cell, "Value").toSafeArray(); + System.out.println("sa: dim=" + sAProdText.getNumDim()); + System.out.println("sa: start row=" + sAProdText.getLBound(1)); + System.out.println("sa: start col=" + sAProdText.getLBound(2)); + System.out.println("sa: end row=" + sAProdText.getUBound(1)); + System.out.println("sa: end col=" + sAProdText.getUBound(2)); + int i; + int lineNumber = 1; + int n = 0; + for (lineNumber = 1; lineNumber < 1000; lineNumber++) { + for (i = 1; i < 4; i++) { + System.out.println((n++) + " " + lineNumber + " " + i + " " + + sAProdText.getString(lineNumber, i)); + /* + * if (sAProdText.getString(lineNumber,i).compareTo("aaaa") != + * 0 ) { System.out.println("Invalid String in line " + + * lineNumber + " Cell " + i + " Value = " + + * sAProdText.getString(lineNumber,i)); stringFound = false; } } + * if (stringFound) { System.out.println("Valid Strings in + * line " + lineNumber); lineNumber++; } + */ } } - if (stringFound) { - System.out.println("Valid Strings in line " + lineNumber); - lineNumber++; - } - */ - } + + Dispatch.call(workbook, "Close"); + System.out.println("Closed File\n"); + } catch (Exception e) { + e.printStackTrace(); + fail("Caught Exception "+e); + } finally { + xl.invoke("Quit", new Variant[] {}); } - - Dispatch.call(workbook, "Close"); - System.out.println("Closed File\n"); - } catch (Exception e) { - e.printStackTrace(); - } finally { - xl.invoke("Quit", new Variant[] {}); } - } } diff --git a/unittest/com/jacob/test/safearray/sa_dispatch.java b/unittest/com/jacob/test/safearray/sa_dispatch.java deleted file mode 100644 index 9c4caab..0000000 --- a/unittest/com/jacob/test/safearray/sa_dispatch.java +++ /dev/null @@ -1,42 +0,0 @@ -package com.jacob.test.safearray; - -import com.jacob.com.*; -import com.jacob.activeX.*; - -class sa_dispatch -{ - public static void main(String args[]) - { - // deprecated - //System.runFinalizersOnExit(true); - - try { - String lang = "VBScript"; - ActiveXComponent sC = new ActiveXComponent("ScriptControl"); - Dispatch sControl = (Dispatch)sC.getObject(); - Dispatch.put(sControl, "Language", lang); - - Variant result = Dispatch.call(sControl, "Eval", args[0]); - System.out.println("eval("+args[0]+") = "+ result); - - // wrap the script control in a variant - Variant v = new Variant(sControl); - - // create a safe array of type dispatch - SafeArray sa = new SafeArray(Variant.VariantDispatch, 1); - - // put the variant in the array - sa.setVariant(0, v); - - // take it back out - Variant v2 = sa.getVariant(0); - Dispatch d = v2.toDispatch(); - - // make sure you can call eval on it - result = Dispatch.call(d, "Eval", args[0]); - System.out.println("eval("+args[0]+") = "+ result); - } catch (ComException e) { - e.printStackTrace(); - } - } -} diff --git a/unittest/com/jacob/test/vbscript/ScriptTest.bat b/unittest/com/jacob/test/vbscript/ScriptTest.bat deleted file mode 100644 index 2db3461..0000000 --- a/unittest/com/jacob/test/vbscript/ScriptTest.bat +++ /dev/null @@ -1,2 +0,0 @@ -java ScriptTest "1+2" -java ScriptTest "()1+2" diff --git a/unittest/com/jacob/test/vbscript/ScriptTest.java b/unittest/com/jacob/test/vbscript/ScriptTest.java index b70039c..9eb2e7b 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest.java @@ -1,50 +1,63 @@ package com.jacob.test.vbscript; import com.jacob.com.*; +import com.jacob.test.BaseTestCase; import com.jacob.activeX.*; /** - * In this case the component is created and used in the same thread - * and it's an Apartment Threaded component, so we call InitSTA. + * In this case the component is created and used in the same thread and it's an + * Apartment Threaded component, so we call InitSTA. + *

    + * May need to run with some command line options (including from inside + * Eclipse). Look in the docs area at the Jacob usage document for command line + * options. */ -class ScriptTest -{ - public static void main(String args[]) throws Exception - { - ComThread.InitSTA(true); - DispatchEvents de = null; - Dispatch sControl = null; +public class ScriptTest extends BaseTestCase { - try { - String lang = "VBScript"; - ActiveXComponent sC = new ActiveXComponent("ScriptControl"); - sControl = (Dispatch)sC.getObject(); - Dispatch.put(sControl, "Language", lang); - ScriptTestErrEvents te = new ScriptTestErrEvents(); - de = new DispatchEvents(sControl, te); - if (de == null){ - System.out.println("Received null when trying to create new DispatchEvents"); - } - Variant result = Dispatch.call(sControl, "Eval", args[0]); - // call it twice to see the objects reused - result = Dispatch.call(sControl, "Eval", args[0]); - // call it 3 times to see the objects reused - result = Dispatch.call(sControl, "Eval", args[0]); - System.out.println("eval("+args[0]+") = "+ result); - } catch (ComException e) { - e.printStackTrace(); - } - finally - { - Integer I = null; - for(int i=1;i<1000000;i++) - { - I = new Integer(i); - } - System.out.println(I); + public void testStupidSpeedTest() { + String lang = "VBScript"; + ActiveXComponent sC = new ActiveXComponent("ScriptControl"); + Dispatch sControl = sC.getObject(); + Dispatch.put(sControl, "Language", lang); + for (int i = 0; i < 10000; i++) { + Dispatch.call(sControl, "Eval", "1+1"); + } + } + + public void testCreatingDispatchEvents() { + ComThread.InitSTA(true); + DispatchEvents de = null; + Dispatch sControl = null; + + try { + String scriptCommand = getSampleVPScriptForEval(); + String lang = "VBScript"; + ActiveXComponent sC = new ActiveXComponent("ScriptControl"); + sControl = (Dispatch) sC.getObject(); + Dispatch.put(sControl, "Language", lang); + ScriptTestErrEvents te = new ScriptTestErrEvents(); + de = new DispatchEvents(sControl, te); + if (de == null) { + System.out + .println("Received null when trying to create new DispatchEvents"); + } + Variant result = Dispatch.call(sControl, "Eval", scriptCommand); + // call it twice to see the objects reused + result = Dispatch.call(sControl, "Eval", scriptCommand); + // call it 3 times to see the objects reused + result = Dispatch.call(sControl, "Eval", scriptCommand); + System.out.println("eval(" + scriptCommand + ") = " + result); + } catch (ComException e) { + e.printStackTrace(); + fail("Caught Exception " + e); + } finally { + Integer I = null; + for (int i = 1; i < 1000000; i++) { + I = new Integer(i); + } + System.out.println(I); ComThread.Release(); ComThread.quitMainSTA(); - } - } + } + } } - diff --git a/unittest/com/jacob/test/vbscript/ScriptTest2.java b/unittest/com/jacob/test/vbscript/ScriptTest2.java index 2add06e..0963b32 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest2.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest2.java @@ -1,98 +1,98 @@ package com.jacob.test.vbscript; import com.jacob.com.*; +import com.jacob.test.BaseTestCase; import com.jacob.activeX.*; /** - * This example demonstrates how to make calls between - * two different STA's. - * First, to create an STA, you need to extend the STA class - * and override its OnInit() method. This method will be called - * in the STA's thread so you can use it to create your COM - * components that will run in that STA. - * If you then try to call methods on those components from other - * threads (STA or MTA) - this will fail. - * You cannot create a component in an STA and call its methods - * from another thread. - * You can use the DispatchProxy to get a proxy to any Dispatch - * that lives in another STA. This object has to be created in the - * STA that houses the Dispatch (in this case it's created in the - * OnInit method). Then, another thread can call the toDispatch() - * method of DispatchProxy to get a local proxy. At most ONE (!) - * thread can call toDispatch(), and the call can be made only once. - * This is because a IStream object is used to pass the proxy, and - * it is only written once and closed when you read it. - * If you need multiple threads to access a Dispatch pointer, then - * create that many DispatchProxy objects. + * This example demonstrates how to make calls between two different STA's. + * First, to create an STA, you need to extend the STA class and override its + * OnInit() method. This method will be called in the STA's thread so you can + * use it to create your COM components that will run in that STA. If you then + * try to call methods on those components from other threads (STA or MTA) - + * this will fail. You cannot create a component in an STA and call its methods + * from another thread. You can use the DispatchProxy to get a proxy to any + * Dispatch that lives in another STA. This object has to be created in the STA + * that houses the Dispatch (in this case it's created in the OnInit method). + * Then, another thread can call the toDispatch() method of DispatchProxy to get + * a local proxy. At most ONE (!) thread can call toDispatch(), and the call can + * be made only once. This is because a IStream object is used to pass the + * proxy, and it is only written once and closed when you read it. If you need + * multiple threads to access a Dispatch pointer, then create that many + * DispatchProxy objects. + *

    + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. */ -class ScriptTest2 extends STA -{ - public static ActiveXComponent sC; - public static DispatchEvents de = null; - public static Dispatch sControl = null; - public static DispatchProxy sCon = null; - public boolean OnInit() - { - try - { - System.out.println("OnInit"); - System.out.println(Thread.currentThread()); - String lang = "VBScript"; - sC = new ActiveXComponent("ScriptControl"); - sControl = (Dispatch)sC.getObject(); +public class ScriptTest2 extends BaseTestCase { + public void testScript2() { + try { + ComThread.InitSTA(); + ScriptTestSTA script = new ScriptTestSTA(); + try { + Thread.sleep(1000); + } catch (InterruptedException ie){ + // should we get this? + } - // sCon can be called from another thread - sCon = new DispatchProxy(sControl); + String scriptCommand = getSampleVPScriptForEval(); + // get a thread-local Dispatch from sCon + Dispatch sc = script.sCon.toDispatch(); - Dispatch.put(sControl, "Language", lang); - ScriptTestErrEvents te = new ScriptTestErrEvents(); - de = new DispatchEvents(sControl, te); - return true; - } - catch (Exception e) - { - e.printStackTrace(); - return false; - } - } + // call a method on the thread-local Dispatch obtained + // from the DispatchProxy. If you try to make the same + // method call on the sControl object - you will get a + // ComException. + Variant result = Dispatch.call(sc, "Eval", scriptCommand); + System.out.println("eval(" + scriptCommand + ") = " + result); + script.quit(); + System.out.println("called quit"); + } catch (ComException e) { + e.printStackTrace(); + fail("caught exception"+e); + } finally { + Integer I = null; + for (int i = 1; i < 1000000; i++) { + I = new Integer(i); + } + System.out.println(I); + ComThread.Release(); + } + } - public void OnQuit() - { - System.out.println("OnQuit"); - } + public class ScriptTestSTA extends STA { - public static void main(String args[]) throws Exception - { - try { - ComThread.InitSTA(); - ScriptTest2 script = new ScriptTest2(); - Thread.sleep(1000); + public DispatchEvents de = null; - // get a thread-local Dispatch from sCon - Dispatch sc = sCon.toDispatch(); + public Dispatch sControl = null; + + public DispatchProxy sCon = null; + + public boolean OnInit() { + try { + System.out.println("OnInit"); + System.out.println(Thread.currentThread()); + String lang = "VBScript"; + sControl = new ActiveXComponent("ScriptControl"); + + // sCon can be called from another thread + sCon = new DispatchProxy(sControl); + + Dispatch.put(sControl, "Language", lang); + ScriptTestErrEvents te = new ScriptTestErrEvents(); + de = new DispatchEvents(sControl, te); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public void OnQuit() { + System.out.println("OnQuit"); + } + + } - // call a method on the thread-local Dispatch obtained - // from the DispatchProxy. If you try to make the same - // method call on the sControl object - you will get a - // ComException. - Variant result = Dispatch.call(sc, "Eval", args[0]); - System.out.println("eval("+args[0]+") = "+ result); - script.quit(); - System.out.println("called quit"); - } catch (ComException e) { - e.printStackTrace(); - } - finally - { - Integer I = null; - for(int i=1;i<1000000;i++) - { - I = new Integer(i); - } - System.out.println(I); - ComThread.Release(); - } - } } - diff --git a/unittest/com/jacob/test/vbscript/ScriptTest2ActiveX.java b/unittest/com/jacob/test/vbscript/ScriptTest2ActiveX.java index 08b38fa..17da960 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest2ActiveX.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest2ActiveX.java @@ -1,96 +1,102 @@ package com.jacob.test.vbscript; -import com.jacob.com.*; -import com.jacob.activeX.*; +import com.jacob.activeX.ActiveXComponent; +import com.jacob.com.ComException; +import com.jacob.com.ComThread; +import com.jacob.com.DispatchEvents; +import com.jacob.com.DispatchProxy; +import com.jacob.com.STA; +import com.jacob.com.Variant; +import com.jacob.test.BaseTestCase; /** - * This example demonstrates how to make calls between - * two different STA's. - * First, to create an STA, you need to extend the STA class - * and override its OnInit() method. This method will be called - * in the STA's thread so you can use it to create your COM - * components that will run in that STA. - * If you then try to call methods on those components from other - * threads (STA or MTA) - this will fail. - * You cannot create a component in an STA and call its methods - * from another thread. - * You can use the DispatchProxy to get a proxy to any Dispatch - * that lives in another STA. This object has to be created in the - * STA that houses the Dispatch (in this case it's created in the - * OnInit method). Then, another thread can call the toDispatch() - * method of DispatchProxy to get a local proxy. At most ONE (!) - * thread can call toDispatch(), and the call can be made only once. - * This is because a IStream object is used to pass the proxy, and - * it is only written once and closed when you read it. - * If you need multiple threads to access a Dispatch pointer, then - * create that many DispatchProxy objects. + * This example demonstrates how to make calls between two different STA's. + * First, to create an STA, you need to extend the STA class and override its + * OnInit() method. This method will be called in the STA's thread so you can + * use it to create your COM components that will run in that STA. If you then + * try to call methods on those components from other threads (STA or MTA) - + * this will fail. You cannot create a component in an STA and call its methods + * from another thread. You can use the DispatchProxy to get a proxy to any + * Dispatch that lives in another STA. This object has to be created in the STA + * that houses the Dispatch (in this case it's created in the OnInit method). + * Then, another thread can call the toDispatch() method of DispatchProxy to get + * a local proxy. At most ONE (!) thread can call toDispatch(), and the call can + * be made only once. This is because a IStream object is used to pass the + * proxy, and it is only written once and closed when you read it. If you need + * multiple threads to access a Dispatch pointer, then create that many + * DispatchProxy objects. + *

    + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. */ -class ScriptTest2ActiveX extends STA -{ - public static ActiveXComponent sC; - public static DispatchEvents de = null; - public static DispatchProxy sCon = null; +public class ScriptTest2ActiveX extends BaseTestCase { + public static ActiveXComponent sC; - public boolean OnInit() - { - try - { - System.out.println("OnInit"); - System.out.println(Thread.currentThread()); - String lang = "VBScript"; - sC = new ActiveXComponent("ScriptControl"); + public static DispatchEvents de = null; - // sCon can be called from another thread - sCon = new DispatchProxy(sC); + public static DispatchProxy sCon = null; - sC.setProperty("Language", lang); - ScriptTestErrEvents te = new ScriptTestErrEvents(); - de = new DispatchEvents(sC, te); - return true; - } - catch (Exception e) - { - e.printStackTrace(); - return false; - } - } + public void testActiveXSTA() { + try { + ComThread.InitSTA(); + ScriptTest2ActiveXSTA script = new ScriptTest2ActiveXSTA(); + try { + Thread.sleep(1000); + } catch (InterruptedException ie){ + // should we get this? + } - public void OnQuit() - { - System.out.println("OnQuit"); - } + // get a thread-local Dispatch from sCon + ActiveXComponent sc = new ActiveXComponent(sCon.toDispatch()); - public static void main(String args[]) throws Exception - { - try { - ComThread.InitSTA(); - ScriptTest2ActiveX script = new ScriptTest2ActiveX(); - Thread.sleep(1000); + // call a method on the thread-local Dispatch obtained + // from the DispatchProxy. If you try to make the same + // method call on the sControl object - you will get a + // ComException. + String scriptCommand = getSampleVPScriptForEval(); + Variant result = sc.invoke("Eval", scriptCommand); + System.out.println("eval(" + scriptCommand + ") = " + result); + script.quit(); + System.out.println("called quit"); + } catch (ComException e) { + e.printStackTrace(); + fail("blew up with Com Exception "+e); + } finally { + Integer I = null; + for (int i = 1; i < 1000000; i++) { + I = new Integer(i); + } + System.out.println(I); + ComThread.Release(); + } + } - // get a thread-local Dispatch from sCon - ActiveXComponent sc = new ActiveXComponent(sCon.toDispatch()); + public class ScriptTest2ActiveXSTA extends STA { - // call a method on the thread-local Dispatch obtained - // from the DispatchProxy. If you try to make the same - // method call on the sControl object - you will get a - // ComException. - Variant result = sc.invoke("Eval", args[0]); - System.out.println("eval("+args[0]+") = "+ result); - script.quit(); - System.out.println("called quit"); - } catch (ComException e) { - e.printStackTrace(); - } - finally - { - Integer I = null; - for(int i=1;i<1000000;i++) - { - I = new Integer(i); - } - System.out.println(I); - ComThread.Release(); - } - } -} + public boolean OnInit() { + try { + System.out.println("OnInit"); + System.out.println(Thread.currentThread()); + String lang = "VBScript"; + sC = new ActiveXComponent("ScriptControl"); + // sCon can be called from another thread + sCon = new DispatchProxy(sC); + + sC.setProperty("Language", lang); + ScriptTestErrEvents te = new ScriptTestErrEvents(); + de = new DispatchEvents(sC, te); + return true; + } catch (Exception e) { + e.printStackTrace(); + return false; + } + } + + public void OnQuit() { + System.out.println("OnQuit"); + } + + } + +} \ No newline at end of file diff --git a/unittest/com/jacob/test/vbscript/ScriptTest3.java b/unittest/com/jacob/test/vbscript/ScriptTest3.java index 77f8a16..51c29b3 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest3.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest3.java @@ -1,68 +1,73 @@ package com.jacob.test.vbscript; import com.jacob.com.*; +import com.jacob.test.BaseTestCase; import com.jacob.activeX.*; /** - * Here we create the ScriptControl component in a separate MTA thread - * and then call the Eval method from the main thread. The main thread - * must also be an MTA thread. If you try to create it as an STA - * then you will not be able to make calls into a component running - * in another thread. + * Here we create the ScriptControl component in a separate MTA thread and then + * call the Eval method from the main thread. The main thread must also be an + * MTA thread. If you try to create it as an STA then you will not be able to + * make calls into a component running in another thread. + *

    + * May need to run with some command line options (including from inside Eclipse). + * Look in the docs area at the Jacob usage document for command line options. */ -class ScriptTest3 extends Thread -{ - public static ActiveXComponent sC; - public static DispatchEvents de = null; - public static Dispatch sControl = null; - public static boolean quit = false; +public class ScriptTest3 extends BaseTestCase { - public void run() - { - try - { - ComThread.InitMTA(); - System.out.println("OnInit"); - String lang = "VBScript"; - sC = new ActiveXComponent("ScriptControl"); - sControl = (Dispatch)sC.getObject(); - Dispatch.put(sControl, "Language", lang); - ScriptTestErrEvents te = new ScriptTestErrEvents(); - de = new DispatchEvents(sControl, te); - System.out.println("sControl="+sControl); - while (!quit) sleep(100); - ComThread.Release(); - } - catch (Exception e) - { - e.printStackTrace(); - } - finally - { - System.out.println("worker thread exits"); - } - } + public static ActiveXComponent sC; - public static void main(String args[]) throws Exception - { - try { - ComThread.InitMTA(); - ScriptTest3 script = new ScriptTest3(); - script.start(); - Thread.sleep(1000); + public static DispatchEvents de = null; - Variant result = Dispatch.call(sControl, "Eval", args[0]); - System.out.println("eval("+args[0]+") = "+ result); - System.out.println("setting quit"); - ScriptTest3.quit = true; - } catch (ComException e) { - e.printStackTrace(); - } - finally - { - System.out.println("main done"); - ComThread.Release(); - } - } + public static Dispatch sControl = null; + + public static boolean quit = false; + + public void testScript() { + try { + ComThread.InitMTA(); + ScriptTest3Inner script = new ScriptTest3Inner(); + script.start(); + try { + Thread.sleep(1000); + } catch (InterruptedException ie){ + // should we get this? + } + + Variant result = Dispatch.call(sControl, "Eval", getSampleVPScriptForEval()); + System.out.println("eval(" + getSampleVPScriptForEval() + ") = " + result); + System.out.println("setting quit"); + ScriptTest3.quit = true; + } catch (ComException e) { + e.printStackTrace(); + fail("Caught excpetion running script with MTA"); + } finally { + System.out.println("main done"); + ComThread.Release(); + } + } + + class ScriptTest3Inner extends Thread { + public void run() { + try { + ComThread.InitMTA(); + System.out.println("OnInit"); + String lang = "VBScript"; + sC = new ActiveXComponent("ScriptControl"); + sControl = (Dispatch) sC.getObject(); + Dispatch.put(sControl, "Language", lang); + ScriptTestErrEvents te = new ScriptTestErrEvents(); + de = new DispatchEvents(sControl, te); + System.out.println("sControl=" + sControl); + while (!quit) + sleep(100); + ComThread.Release(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + System.out.println("worker thread exits"); + } + } + + } } - diff --git a/unittest/com/jacob/test/vbscript/ScriptTest3ActiveX.java b/unittest/com/jacob/test/vbscript/ScriptTest3ActiveX.java index 7578ddf..1a20f53 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTest3ActiveX.java +++ b/unittest/com/jacob/test/vbscript/ScriptTest3ActiveX.java @@ -1,66 +1,72 @@ package com.jacob.test.vbscript; import com.jacob.com.*; +import com.jacob.test.BaseTestCase; import com.jacob.activeX.*; /** - * Here we create the ScriptControl component in a separate MTA thread - * and then call the Eval method from the main thread. The main thread - * must also be an MTA thread. If you try to create it as an STA - * then you will not be able to make calls into a component running - * in another thread. + * Here we create the ScriptControl component in a separate MTA thread and then + * call the Eval method from the main thread. The main thread must also be an + * MTA thread. If you try to create it as an STA then you will not be able to + * make calls into a component running in another thread. + *

    + * May need to run with some command line options (including from inside + * Eclipse). Look in the docs area at the Jacob usage document for command line + * options. */ -class ScriptTest3ActiveX extends Thread -{ - public static ActiveXComponent sC; - public static DispatchEvents de = null; - public static boolean quit = false; +public class ScriptTest3ActiveX extends BaseTestCase { + public static ActiveXComponent sC; - public void run() - { - try - { - ComThread.InitMTA(); - System.out.println("OnInit"); - String lang = "VBScript"; - sC = new ActiveXComponent("ScriptControl"); - sC.setProperty("Language", lang); - ScriptTestErrEvents te = new ScriptTestErrEvents(); - de = new DispatchEvents(sC, te); - System.out.println("sControl="+sC); - while (!quit) sleep(100); - ComThread.Release(); - } - catch (Exception e) - { - e.printStackTrace(); - } - finally - { - System.out.println("worker thread exits"); - } - } + public static DispatchEvents de = null; - public static void main(String args[]) throws Exception - { - try { - ComThread.InitMTA(); - ScriptTest3ActiveX script = new ScriptTest3ActiveX(); - script.start(); - Thread.sleep(1000); + public static boolean quit = false; - Variant result = sC.invoke("Eval", args[0]); - System.out.println("eval("+args[0]+") = "+ result); - System.out.println("setting quit"); - ScriptTest3ActiveX.quit = true; - } catch (ComException e) { - e.printStackTrace(); - } - finally - { - System.out.println("main done"); - ComThread.Release(); - } - } + public void testYetAnotherScriptTest() { + try { + ComThread.InitMTA(); + ScriptTest3ActiveXInner script = new ScriptTest3ActiveXInner(); + script.start(); + try { + Thread.sleep(1000); + } catch (InterruptedException ie) { + // should we get this? + } + + Variant result = sC.invoke("Eval", getSampleVPScriptForEval()); + System.out + .println("eval(" + getSampleVPScriptForEval() + + ") = " + result); + System.out.println("setting quit"); + ScriptTest3ActiveX.quit = true; + } catch (ComException e) { + e.printStackTrace(); + fail("Caught ComException " + e); + } finally { + System.out.println("main done"); + ComThread.Release(); + } + } + + public class ScriptTest3ActiveXInner extends Thread { + public void run() { + try { + ComThread.InitMTA(); + System.out.println("OnInit"); + String lang = "VBScript"; + sC = new ActiveXComponent("ScriptControl"); + sC.setProperty("Language", lang); + ScriptTestErrEvents te = new ScriptTestErrEvents(); + de = new DispatchEvents(sC, te); + System.out.println("sControl=" + sC); + while (!quit) + sleep(100); + ComThread.Release(); + } catch (Exception e) { + e.printStackTrace(); + } finally { + System.out.println("worker thread exits"); + } + } + + } } - diff --git a/unittest/com/jacob/test/vbscript/ScriptTestActiveX.java b/unittest/com/jacob/test/vbscript/ScriptTestActiveX.java index 0d94b56..9d3a57a 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTestActiveX.java +++ b/unittest/com/jacob/test/vbscript/ScriptTestActiveX.java @@ -1,16 +1,19 @@ package com.jacob.test.vbscript; import com.jacob.com.*; +import com.jacob.test.BaseTestCase; import com.jacob.activeX.*; /** * In this case the component is created and used in the same thread * and it's an Apartment Threaded component, so we call InitSTA. + *

    + * May need to run with some command line options (including from inside + * Eclipse). Look in the docs area at the Jacob usage document for command line + * options. */ -class ScriptTestActiveX -{ - public static void main(String args[]) throws Exception - { +public class ScriptTestActiveX extends BaseTestCase { + public void testActiveXScript() { ComThread.InitSTA(true); DispatchEvents de = null; @@ -24,12 +27,12 @@ class ScriptTestActiveX System.out.println("null returned when trying to create DispatchEvents"); } Variant result; - result = sC.invoke("Eval",args[0]); + result = sC.invoke("Eval",getSampleVPScriptForEval()); // call it twice to see the objects reused - result = sC.invoke("Eval",args[0]); + result = sC.invoke("Eval",getSampleVPScriptForEval()); // call it 3 times to see the objects reused - result = sC.invoke("Eval",args[0]); - System.out.println("eval("+args[0]+") = "+ result); + result = sC.invoke("Eval",getSampleVPScriptForEval()); + System.out.println("eval("+getSampleVPScriptForEval()+") = "+ result); } catch (ComException e) { e.printStackTrace(); } diff --git a/unittest/com/jacob/test/vbscript/ScriptTestErrEvents.java b/unittest/com/jacob/test/vbscript/ScriptTestErrEvents.java index 1133fe1..9be2f38 100644 --- a/unittest/com/jacob/test/vbscript/ScriptTestErrEvents.java +++ b/unittest/com/jacob/test/vbscript/ScriptTestErrEvents.java @@ -1,12 +1,13 @@ - package com.jacob.test.vbscript; import com.jacob.com.Variant; +import com.jacob.test.BaseTestCase; /** * Extracted from ScriptTest so everyone can see this + * Made a test solely because it made the ant test easier */ -public class ScriptTestErrEvents { +public class ScriptTestErrEvents extends BaseTestCase { public void Error(Variant[] args) { diff --git a/unittest/com/jacob/test/vbscript/speed.java b/unittest/com/jacob/test/vbscript/speed.java deleted file mode 100644 index 778da05..0000000 --- a/unittest/com/jacob/test/vbscript/speed.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.jacob.test.vbscript; - -import com.jacob.com.*; -import com.jacob.activeX.*; - -class speed -{ - public static void main(String args[]) - { - String lang = "VBScript"; - ActiveXComponent sC = new ActiveXComponent("ScriptControl"); - Dispatch sControl = sC.getObject(); - Dispatch.put(sControl, "Language", lang); - for(int i=0;i<10000;i++) { - Dispatch.call(sControl, "Eval", "1+1"); - } - } -} diff --git a/unittest/com/jacob/test/windowsmedia/WMPlayer.java b/unittest/com/jacob/test/windowsmedia/WMPlayer.java index 831c470..4f7e152 100644 --- a/unittest/com/jacob/test/windowsmedia/WMPlayer.java +++ b/unittest/com/jacob/test/windowsmedia/WMPlayer.java @@ -9,20 +9,22 @@ package com.jacob.test.windowsmedia; * Look in the docs area at the Jacob usage document for command line options. */ import com.jacob.activeX.*; +import com.jacob.test.BaseTestCase; -public class WMPlayer { +public class WMPlayer extends BaseTestCase { - public static void main(String[] args){ + public void testOpenWMPlayer() { ActiveXComponent wmp = null; wmp = new ActiveXComponent("WMPlayer.OCX"); - - // the sourceforge posting didn't post all the code so this is all we have - // we need some other information on how to set the document + + // the sourceforge posting didn't post all the code so this is all we + // have we need some other information on how to set the document // so that we have a url to open - for ( int i= 0 ; i < 1000 ; i++){ - System.out.println("the wmp url is "+ wmp.getProperty("URL").toString()); + for (int i = 0; i < 1000; i++) { + System.out.println("the wmp url is " + + wmp.getProperty("URL").toString()); } - - } - + + } + }