Compare commits

...

37 Commits

Author SHA1 Message Date
Andrew Johnson
5ca1bb3bd5 Set SNAPSHOT for 3.14.12.7 final release 2017-12-15 16:06:08 -06:00
Andrew Johnson
f6be3c7f70 Set snapshot to -rc1-DEV 2017-12-08 16:40:08 -06:00
Andrew Johnson
00924dcba0 About to tag 3.14.12.7-rc1 2017-12-08 16:37:03 -06:00
Andrew Johnson
5278799575 aSubRecord: Copy the right amount of data
Initialize OVLx from VALx with NEVx elements, size from FTVx
2017-11-15 20:59:06 -06:00
Michael Davidsaver
2af98c33c9 std/rec: aSub handle INAM changing outputs
Allow EFLG="On Change" to work with INAM.
2017-11-08 14:29:30 -06:00
Andrew Johnson
22debb3532 Fix for LP: #1702298 2017-09-25 15:41:31 -05:00
Andrew Johnson
c441cdd5a4 Adjust comments about EPICS_TIMEZONE 2017-09-25 12:14:48 -05:00
Andrew Johnson
13fa1e2722 Travis: Use 'make test-results' for more compact output 2017-09-07 17:39:42 -05:00
Andrew Johnson
fad89189da Fix typo in CAref.html 2017-09-07 17:38:58 -05:00
Andrew Johnson
4ab56518a0 Add readline support to linux-xscale_be rules
Also moves cross-build config to the right host-arch's
2017-08-18 15:14:42 -05:00
Andrew Johnson
80dbc7aeef Clean up the cross-build rules slightly 2017-08-18 15:10:13 -05:00
Andrew Johnson
238f6772bd Dirk's simpler VxWorks version rules 2017-08-18 15:06:38 -05:00
Andrew Johnson
dc9859cee9 Fix RPATH and readline for linux-arm cross-builds 2017-08-18 11:59:17 -05:00
Andrew Johnson
5d5f27a486 Don't set RPATH if STATIC_BUILD=YES 2017-08-18 11:57:50 -05:00
Andrew Johnson
ad6a16d7c4 Update EPICS_TIMEZONE settings, extend to 2022 2017-08-18 11:33:17 -05:00
Michael Davidsaver
5c8e5c52ef rsrv: fix recv() error handling on WIN32
For WIN32 osiSockIoctl_t is unsigned, so

> osiSockIoctl_t nchars = recv(...

is casting signed -> unsigned which treats
errors as success.
2017-08-01 17:02:41 +02:00
Michael Davidsaver
546df1c1f0 rsrv: export CASDEBUG to iocsh 2017-08-01 17:02:41 +02:00
Michael Davidsaver
603331e7a5 rsrv: flush any queued messages before forced disconnect
Avoid loss of various ERROR messages which camessage()
has queued.
2017-08-01 16:44:48 +02:00
Michael Davidsaver
4b272cc0cf rsrv: locking in cas_send_bs_msg()
Must lock around "pclient->send.stk = 0u;"
2017-08-01 16:44:48 +02:00
Michael Davidsaver
619a99bf99 rsrv: missing send lock around send_err() 2017-08-01 16:44:48 +02:00
Michael Davidsaver
1f8cb740f1 rsrv: drop un-commited VERSION message
This is a no-op as cas_commit_msg() isn't called.
A VERSION message is already queued during create_tcp_client().
2017-08-01 16:44:29 +02:00
Michael Davidsaver
322f7a97de rsrv: add some comments 2017-08-01 16:44:29 +02:00
Michael Davidsaver
0fc770166c rsrv: avoid possible overflow in vsend_err()
Accounting of message size doesn't take into account
space used by header of failed message (16 or 24 bytes).
This would allow a theoretical really long error message
to overflow the send buffer by 16 or 24 bytes.
2017-08-01 16:44:08 +02:00
Andrew Johnson
1a70855e25 Use static strings for epicsInterruptContextMessage()
The callbackRequest() routine was passing a stack-allocated
string to epicsInterruptContextMessage() but on RTEMS the
pointer is queued without copying the string. This fix uses
static strings for the 3 messages instead.

Fixes LP: #1705219
2017-07-24 11:19:20 -05:00
Andrew Johnson
6b5e7da4fd catools: dbr_long_t is only 32 bits wide
Don't print it as a native long.
Fixes LP: #1699332
2017-06-20 15:49:41 -05:00
Andrew Johnson
a1dc16848c configure: Fix include CONFIG_APP_INCLUDE
which needs to happen *after* CONFIG_SITE overrides.
2017-06-14 10:03:43 -05:00
Andrew Johnson
2819d7ea3d Posix epicsEventWaitWithTimeout() max delay
Limit timeouts on Posix to max-out at 10 years.
Adds a test that will fail when that time-out hits Y2038 on
systems where time_t is still a 32-bit integer.
2017-06-14 10:01:23 -05:00
Andrew Johnson
6ef995525a Restore the use of DBL_MAX in timerQueue.cpp 2017-06-09 13:44:30 -05:00
Andrew Johnson
18dee384ec Fix tv_sec casts to use time_t, not long 2017-06-09 12:20:16 -05:00
Andrew Johnson
b369aa67f1 Use 1000 years as 'forever' in timers
DBL_MAX causes problems...
2017-06-08 21:55:12 -05:00
Andrew Johnson
c853234e01 Remove artificial 60-minute timeout limit (Posix) 2017-06-08 09:53:07 -04:00
Andrew Johnson
9c859ffdca Protect casStatsFetch() if called before rsrv_init()
Also ensures clientQ is initialized before creating clientQlock.

Fixes LP: #1694966
2017-06-01 15:37:34 -05:00
Andrew Johnson
0dc850f4ec A gitignore pattern for vi on MacOS 2017-05-30 17:13:56 -05:00
Andrew Johnson
672fd16ec8 Add make targets test-results and clean-tests
These are mainly intended for CI builds.
2017-05-19 15:44:15 -05:00
Ralph Lange
dcadeac903 ci: add appveyor configuration 2017-05-19 13:38:39 +09:00
Andrew Johnson
b7b3dd2b37 Support for 'make junitfiles' target.
The Perl XML::Generator module must be installed to use this.
2017-05-18 16:31:43 -05:00
Xiaoqiang Wang
82396ee3ef fix data size of gdd container type
getDataSizeElement of gdd container returns the number of sub fields.
It has to be called on the "value" field. This fix has already been done
in monitorReponse.
2017-05-10 10:22:13 -05:00
47 changed files with 1176 additions and 178 deletions

1
.gitignore vendored
View File

@@ -10,3 +10,4 @@ O.*/
/QtC-*
*.orig
*.log
.*.swp

86
appveyor.yml Normal file
View File

@@ -0,0 +1,86 @@
# AppVeyor configuration for EPICS Base
# Ralph Lange <ralph.lange@gmx.de>
# Copyright (c) 2016-2017 ITER Organization
# Version format
version: base-{branch}-{build}
#---------------------------------#
# repository cloning #
#---------------------------------#
# Called at very beginning, before repo cloning
init:
# Set autocrlf to make batch files work
- git config --global core.autocrlf true
# Set clone depth (do not fetch complete history)
clone_depth: 2
# Skipping commits affecting only specific files
skip_commits:
files:
- 'documentation/*'
- 'templates/*'
- '**/*.html'
- '**/*.md'
#---------------------------------#
# build matrix configuration #
#---------------------------------#
# Build Configurations: dll/static, regular/debug
configuration:
- dynamic
- static
- dynamic-debug
- static-debug
# Environment variables: compiler toolchain
environment:
matrix:
- TOOLCHAIN: 9.0
- TOOLCHAIN: 10.0
- TOOLCHAIN: 11.0
- TOOLCHAIN: 12.0
- TOOLCHAIN: 14.0
- TOOLCHAIN: cygwin
- TOOLCHAIN: mingw
# Platform: architecture
platform:
- x86
- x64
# Matrix configuration: allow specific failing jobs
matrix:
exclude:
# VS Express installs don't have the 64 bit compiler
- platform: x64
TOOLCHAIN: 9.0
- platform: x64
TOOLCHAIN: 10.0
#---------------------------------#
# building & testing #
#---------------------------------#
install:
- cmd: ci/appveyor-prepare.bat
build_script:
- cmd: ci/appveyor-make.bat
test_script:
- cmd: ci/appveyor-make.bat runtests
#---------------------------------#
# notifications #
#---------------------------------#
notifications:
- provider: Slack
incoming_webhook:
secure: RYOm3FIUYeZGjWKaeTVKwq+C3fzK54AKwbmAoECED45mex3lN+8HmrC845a6mg9xPUJ/ND51RopWVaKDD9/UzaM0SO195RQLKqUTIUafiuM=

118
ci/appveyor-make.bat Normal file
View File

@@ -0,0 +1,118 @@
:: Universal build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - toolchain version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static]
:: PLATFORM - architecture [x86/x64]
::
:: All command line args are passed to make
Setlocal EnableDelayedExpansion
set "ST="
if /i "%CONFIGURATION%"=="static" set ST=-static
set OS=64BIT
if "%PLATFORM%"=="x86" set OS=32BIT
echo [INFO] Platform: %OS%
:: Use parallel make, except for 3.14
set "MAKEARGS=-j2 -Otarget"
if "%APPVEYOR_REPO_BRANCH%"=="3.14" set MAKEARGS=
if "%TOOLCHAIN%"=="cygwin" (
set "MAKE=make"
if "%OS%"=="64BIT" (
set "EPICS_HOST_ARCH=cygwin-x86_64"
set "INCLUDE=C:\cygwin64\include;%INCLUDE%"
set "PATH=C:\cygwin64\bin;%PATH%"
echo [INFO] Cygwin Toolchain 64bit
) else (
set "EPICS_HOST_ARCH=cygwin-x86"
set "INCLUDE=C:\cygwin\include;%INCLUDE%"
set "PATH=C:\cygwin\bin;%PATH%"
echo [INFO] Cygwin Toolchain 32bit
)
echo [INFO] Compiler Version
gcc -v
goto Finish
)
if "%TOOLCHAIN%"=="mingw" (
set "MAKE=mingw32-make"
if "%OS%"=="64BIT" (
set "EPICS_HOST_ARCH=windows-x64-mingw"
set "INCLUDE=C:\tools\mingw64\include;%INCLUDE%"
set "PATH=C:\tools\mingw64\bin;%PATH%"
echo [INFO] MinGW Toolchain 64bit
) else (
set "EPICS_HOST_ARCH=win32-x86-mingw"
set "INCLUDE=C:\tools\mingw32\include;%INCLUDE%"
set "PATH=C:\tools\mingw32\bin;%PATH%"
echo [INFO] MinGW Toolchain 32bit
)
echo [INFO] Compiler Version
gcc -v
goto Finish
)
set "VSINSTALL=C:\Program Files (x86)\Microsoft Visual Studio %TOOLCHAIN%"
set "MAKE=C:\tools\make"
if "%OS%"=="64BIT" (
set EPICS_HOST_ARCH=windows-x64%ST%
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" amd64
where cl
if !ERRORLEVEL! NEQ 0 (
call "%VSINSTALL%\VC\vcvarsall.bat" x86_amd64
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
)
goto MSFound
)
if exist "%VSINSTALL%\VC\bin\amd64\vcvars64.bat" (
call "%VSINSTALL%\VC\bin\amd64\vcvars64.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
) else (
set EPICS_HOST_ARCH=win32-x86%ST%
if exist "%VSINSTALL%\VC\vcvarsall.bat" (
call "%VSINSTALL%\VC\vcvarsall.bat" x86
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\VC\bin\vcvars32.bat" (
call "%VSINSTALL%\VC\bin\vcvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
if exist "%VSINSTALL%\Common7\Tools\vsvars32.bat" (
call "%VSINSTALL%\Common7\Tools\vsvars32.bat"
where cl
if !ERRORLEVEL! NEQ 0 goto MSMissing
goto MSFound
)
)
:MSMissing
echo [INFO] Installation for MSVC Toolchain %TOOLCHAIN% / %OS% seems to be missing
exit 1
:MSFound
echo [INFO] Microsoft Visual Studio Toolchain %TOOLCHAIN%
echo [INFO] Compiler Version
cl
:Finish
echo [INFO] EPICS_HOST_ARCH: %EPICS_HOST_ARCH%
echo [INFO] Make version
%MAKE% --version
echo [INFO] Perl version
perl --version
%MAKE% %MAKEARGS% %*

70
ci/appveyor-prepare.bat Normal file
View File

@@ -0,0 +1,70 @@
:: Build script for AppVeyor (https://ci.appveyor.com/)
:: Environment:
:: TOOLCHAIN - Toolchain Version [9.0/10.0/11.0/12.0/14.0/cygwin/mingw]
:: CONFIGURATION - determines EPICS build [dynamic/static, -debug]
:: PLATFORM - "x86" -> use 32bit architecture
::
:: Prepares an Appveyor build by excuting the following steps
:: - Set up configure\CONFIG_SITE for static vs. dynamic build
:: - Install Cygwin / Mingw (TOOLCHAIN setting) in the in the appropriate flavor
:: - Download and install Make-4.1 from EPICS download page
Setlocal EnableDelayedExpansion
set OS=64BIT
if "%PLATFORM%"=="x86" set OS=32BIT
echo [INFO] Platform: %OS%
if "%TOOLCHAIN%"=="cygwin" (
echo.%CONFIGURATION% | findstr /C:"static">nul && (
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
echo [INFO] EPICS set up for static build
) || (
echo [INFO] EPICS set up for dynamic build
)
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
echo HOST_OPT=NO>> configure\CONFIG_SITE
echo [INFO] EPICS set up for debug build
) || (
echo [INFO] EPICS set up for optimized build
)
if "%OS%"=="64BIT" (
echo [INFO] Installing Cygwin 64bit and dependencies
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86_64.exe', 'C:\cygwin64\setup-x86_64.exe')"
C:\cygwin64\setup-x86_64.exe -q -P "libreadline-devel,libncursesw-devel"
) else (
echo [INFO] Installing Cygwin 32bit and dependencies
@powershell -Command "(new-object net.webclient).DownloadFile('http://www.cygwin.com/setup-x86.exe', 'C:\cygwin\setup-x86.exe')"
C:\cygwin\setup-x86.exe -q -P "libreadline-devel,libncursesw-devel"
)
)
if "%TOOLCHAIN%"=="mingw" (
echo.%CONFIGURATION% | findstr /C:"static">nul && (
echo SHARED_LIBRARIES=NO>> configure\CONFIG_SITE
echo STATIC_BUILD=YES>> configure\CONFIG_SITE
echo [INFO] EPICS set up for static build
) || (
echo [INFO] EPICS set up for dynamic build
)
echo.%CONFIGURATION% | findstr /C:"debug">nul && (
echo HOST_OPT=NO>> configure\CONFIG_SITE
echo [INFO] EPICS set up for debug build
) || (
echo [INFO] EPICS set up for optimized build
)
if "%OS%"=="64BIT" (
echo [INFO] Installing MinGW 64bit
cinst mingw || cinst mingw
) else (
echo [INFO] Installing MinGW 32bit
cinst mingw --x86 || cinst mingw --x86
)
)
echo [INFO] Installing Make 4.1
@powershell -Command "(new-object net.webclient).DownloadFile('https://www.aps.anl.gov/epics/download/tools/make-4.1-win64.zip', 'C:\tools\make-4.1.zip')"
cd \tools
"C:\Program Files\7-Zip\7z" e make-4.1.zip

View File

@@ -86,5 +86,5 @@ make -j2 $EXTRA
if [ "$TEST" != "NO" ]
then
make tapfiles
find . -name '*.tap' -print0 | xargs -0 -n1 prove -e cat -f
make -s test-results
fi

View File

@@ -75,17 +75,17 @@ ifdef T_A
#
-include $(CONFIG)/os/CONFIG.$(EPICS_HOST_ARCH).$(T_A)
# Site specific target and host-target definitions and overrides
#
-include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A)
-include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
# RELEASE file specific definitions
#
ifneq ($(CONFIG),$(TOP)/configure)
-include $(CONFIG)/CONFIG_APP_INCLUDE
endif
# Site specific target and host-target definitions
#
-include $(CONFIG)/os/CONFIG_SITE.Common.$(T_A)
-include $(CONFIG)/os/CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A)
endif # ifdef T_A

View File

@@ -17,14 +17,14 @@ BUILD_CLASS = CROSS
# ifdef CROSS looks better than ifeq ($(BUILD_CLASS),CROSS)
CROSS = YES
GNU_TARGET_INCLUDE_DIR = $(GNU_TARGET:%= $(GNU_DIR)/%/include)
GNU_TARGET_LIB_DIR = $(GNU_TARGET:%= $(GNU_DIR)/%/lib)
GNU_TARGET_INCLUDE_DIR = $(wildcard $(GNU_TARGET:%=$(GNU_DIR)/%/include))
GNU_TARGET_LIB_DIR = $(wildcard $(GNU_TARGET:%=$(GNU_DIR)/%/lib))
CROSS_INCLUDES = $(addprefix -I,$(GNU_TARGET_INCLUDE_DIR))
CROSS_LDFLAGS = $(addprefix -L,$(GNU_TARGET_LIB_DIR))
CROSS_INCLUDES = $(GNU_TARGET_INCLUDE_DIR:%=-I%)
CROSS_LDFLAGS = $(GNU_TARGET_LIB_DIR:%=-L%)
CMPLR_PREFIX_CROSS=$(addsuffix -,$(GNU_TARGET))
CMPLR_PREFIX=$(CMPLR_PREFIX_$(BUILD_CLASS))
CMPLR_PREFIX_CROSS = $(addsuffix -,$(GNU_TARGET))
CMPLR_PREFIX = $(CMPLR_PREFIX_$(BUILD_CLASS))
# Cross builds usually use the gnu compiler
include $(CONFIG)/CONFIG.gnuCommon

View File

@@ -66,6 +66,7 @@ DBTOMENUH = $(call PATH_FILTER, $(TOOLS)/dbToMenuH$(HOSTEXE))
REGISTERRECORDDEVICEDRIVER = $(PERL) $(TOOLS)/registerRecordDeviceDriver.pl
CONVERTRELEASE = $(PERL) $(call FIND_TOOL,convertRelease.pl)
FULLPATHNAME = $(PERL) $(TOOLS)/fullPathName.pl
TAPTOJUNIT = $(PERL) $(TOOLS)/tap-to-junit-xml.pl
#-------------------------------------------------------
# tools for installing libraries and products

View File

@@ -28,10 +28,10 @@ EPICS_MODIFICATION = 12
# EPICS_PATCH_LEVEL must be a number (win32 resource file requirement)
# Not included if zero
EPICS_PATCH_LEVEL = 6
EPICS_PATCH_LEVEL = 7
# This will end in -DEV between official releases
EPICS_DEV_SNAPSHOT=-DEV
#EPICS_DEV_SNAPSHOT=-DEV
#EPICS_DEV_SNAPSHOT=-pre1
#EPICS_DEV_SNAPSHOT=-pre1-DEV
#EPICS_DEV_SNAPSHOT=-pre2
@@ -40,7 +40,7 @@ EPICS_DEV_SNAPSHOT=-DEV
#EPICS_DEV_SNAPSHOT=-rc1-DEV
#EPICS_DEV_SNAPSHOT=-rc2
#EPICS_DEV_SNAPSHOT=-rc2-DEV
#EPICS_DEV_SNAPSHOT=
EPICS_DEV_SNAPSHOT=
# No changes should be needed below here

View File

@@ -121,11 +121,10 @@ CROSS_COMPILER_TARGET_ARCHS=
#
CROSS_COMPILER_HOST_ARCHS=
# The 'make runtests' and 'make tapfiles' build targets normally only run
# The 'runtests', 'tapfiles' and 'junitfiles' make targets normally only run
# self-tests for the EPICS_HOST_ARCH architecture. If the host can execute
# the self-test programs for any other cross-built architectures such as
# a -debug architecture, those architectures can be named here.
#
# a -debug architecture, those architectures must be named in this variable:
CROSS_COMPILER_RUNTEST_ARCHS=
# Build shared libraries?

View File

@@ -13,7 +13,7 @@
#
# CONFIG_SITE_ENV - EPICS Environment Parameter Site configuration file
#
# This file is read by the script base/src/libCom/env/bldEnvdata.pl
# This file is read by the script base/src/libCom/env/bldEnvData.pl
# Variable definitions must take the form
# VAR = VALUE
# or
@@ -26,31 +26,47 @@
# Time service:
# EPICS_TIMEZONE
# local timezone info for vxWorks and RTEMS IOCs. The format is
# <name>::<minutesWest>:<start daylight>:<end daylight>
# where the start and end are mmddhh - that is month,day,hour
# e.g. for ANL in 2016: EPICS_TIMEZONE=CUS::360:031302:110602
# Local timezone info for vxWorks and RTEMS. The format is
# <name>::<minutesWest>:<startDST>:<endDST>
# where <name> is only used by strftime() for %Z conversions,
# and <startDST> and <endDST> are mmddhh - that is month,day,hour
# e.g. for ANL in 2018: EPICS_TIMEZONE=CUS::360:031102:110402
# The future dates below assume the rules don't get changed;
# see http://www.timeanddate.com/time/dst/2018.html to check.
#
# DST for 2016 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
# DST for 2017 US: Mar 12 - Nov 05
# EU: Mar 26 - Oct 29
EPICS_TIMEZONE = CUS::360:031202:110502
#EPICS_TIMEZONE = MET::-60:032602:102902
#
# DST for 2018 US: Mar 11 - Nov 04
# EU: Mar 25 - Oct 28
#EPICS_TIMEZONE = CUS::360:031102:110402
#EPICS_TIMEZONE = MET::-60:032502:102802
#
# DST for 2019 US: Mar 10 - Nov 03
# EU: Mar 31 - Oct 27
#EPICS_TIMEZONE = CUS::360:031002:110302
#EPICS_TIMEZONE = MET::-60:033102:102702
#
# DST for 2020 US: Mar 08 - Nov 01
# EU: Mar 29 - Oct 25
#EPICS_TIMEZONE = CUS::360:030802:110102
#EPICS_TIMEZONE = MET::-60:032902:102502
#
# DST for 2021 US: Mar 14 - Nov 07
# EU: Mar 28 - Oct 31
# (see: http://www.timeanddate.com/time/dst/2016.html etc. )
#EPICS_TIMEZONE = CUS::360:031402:110702
#EPICS_TIMEZONE = MET::-60:032802:103102
#
# These values are for 2016:
EPICS_TIMEZONE=CUS::360:031302:110602
#EPICS_TIMEZONE=MET::-60:032702:103002
# DST for 2022 US: Mar 13 - Nov 06
# EU: Mar 27 - Oct 30
#EPICS_TIMEZONE = CUS::360:031302:110602
#EPICS_TIMEZONE = MET::-60:032702:103002
# EPICS_TS_NTP_INET
# NTP time server ip address. Uses boot host if not set.
# NTP time server ip address for VxWorks and RTEMS.
# IOC will use its boot host if this is not set.
EPICS_TS_NTP_INET=
# IOC Shell:

View File

@@ -134,7 +134,7 @@ ACTIONS += build
ACTIONS += install
ACTIONS += buildInstall
ACTIONS += browse
ACTIONS += runtests tapfiles
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
actionArchTargets = $(foreach x, $(ACTIONS),\ $(foreach arch,$(BUILD_ARCHS), $(x)$(DIVIDER)$(arch)))
@@ -150,6 +150,7 @@ buildInstall : build
rebuild: clean install
.PHONY: all inc build install clean rebuild buildInstall
.PHONY: runtests tapfiles clean-tests test-results junitfiles
$(actionArchTargets) $(BUILD_ARCHS):install
$(cleanArchTargets):clean

View File

@@ -14,7 +14,7 @@ ACTIONS += build
ACTIONS += install
ACTIONS += buildInstall
ACTIONS += browse
ACTIONS += runtests tapfiles
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
#ACTIONS += rebuild
actionArchTargets = $(foreach action, $(ACTIONS), \

View File

@@ -101,6 +101,7 @@ endif
ifneq (,$(findstring $(T_A),$(EPICS_HOST_ARCH) $(CROSS_COMPILER_RUNTEST_ARCHS)))
RUNTESTS_ENABLED = YES
TAPFILES += $(TESTSCRIPTS:.t=.tap)
JUNITFILES += $(TAPFILES:.tap=.xml)
endif
#---------------------------------------------------------------
@@ -148,7 +149,7 @@ clean::
$(INC) $(TARGETS) $(DLL_LINK_LIBNAME) $(TDS) \
*.out MakefileInclude $(LOADABLE_SHRLIBNAME) *.manifest *.exp \
$(COMMON_INC) $(HDEPENDS_FILES) $(PRODTARGETS) \
$(TESTSCRIPTS) $(TAPFILES)
$(TESTSCRIPTS) $(TAPFILES) $(JUNITFILES)
ifdef RES
@$(RM) *$(RES)
endif
@@ -353,7 +354,23 @@ testspec: $(TESTSCRIPTS)
$(if $^, @echo Tests: $^ >> $@)
$(if $(TESTSPEC_$(OS_CLASS)), @echo "Harness: $(TESTSPEC_$(OS_CLASS))" >> $@)
test-results: tapfiles
ifneq ($(TAPFILES),)
ifdef RUNTESTS_ENABLED
prove --failures --ext .tap --exec cat --color $(TAPFILES)
endif
endif
clean-tests:
ifneq ($(TAPFILES),)
$(RM) $(TAPFILES)
endif
ifneq ($(JUNITFILES),)
$(RM) $(JUNITFILES)
endif
tapfiles: $(TESTSCRIPTS) $(TAPFILES)
junitfiles: $(JUNITFILES)
# A .tap file is the output from running the associated test script
%.tap: %.t
@@ -361,6 +378,9 @@ ifdef RUNTESTS_ENABLED
-$(PERL) $< -tap > $@
endif
%.xml: %.tap
$(TAPTOJUNIT) --puretap --output $@ --input $< $*
# If there's a perl test script (.plt) available, use it
%.t: ../%.plt
@$(RM) $@
@@ -494,7 +514,8 @@ $(INSTALL_TEMPLATES_SUBDIR)/%: %
.PRECIOUS: $(COMMON_INC)
.PHONY: all inc build install clean rebuild buildInstall
.PHONY: runtests checkRelease warnRelease noCheckRelease
.PHONY: runtests tapfiles clean-tests test-results junitfiles
.PHONY: checkRelease warnRelease noCheckRelease
endif # BASE_RULES_BUILD
# EOF RULES_BUILD

View File

@@ -9,7 +9,7 @@
ARCHS += $(BUILD_ARCHS)
ACTIONS += inc build install buildInstall clean realclean archclean
ACTIONS += runtests tapfiles
ACTIONS += runtests tapfiles clean-tests test-results junitfiles
dirActionArchTargets = $(foreach dir, $(DIRS), \
$(foreach action, $(ACTIONS), \

View File

@@ -58,6 +58,7 @@ help:
@echo " Cannot be used within an O.<arch> dir"
@echo " rebuild - Same as clean install"
@echo " archclean - Removes O.<arch> dirs but not O.Common dir"
@echo " runtests - Run self-tests, summarize results"
@echo "\"Partial\" build targets supported by Makefiles:"
@echo " inc$(DIVIDER)<arch> - Installs <arch> only header files."
@echo " build$(DIVIDER)<arch> - Builds and installs <arch> only."

View File

@@ -15,5 +15,14 @@ ARCH_CLASS = xscale
ifeq ($(BUILD_CLASS),CROSS)
VALID_BUILDS = Ioc
GNU_TARGET = xscale_be
CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET))
CMPLR_PREFIX = $(GNU_TARGET:%=%-)
# Configure for readline if requested
OP_SYS_INCLUDES += $(READLINE_DIR:%=-I%/include)
READLINE_LDFLAGS = $(READLINE_DIR:%=-L%/lib)
RUNTIME_LDFLAGS_READLINE_YES_NO = $(READLINE_DIR:%=-Wl,-rpath,%/lib)
RUNTIME_LDFLAGS += \
$(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
SHRLIBDIR_LDFLAGS += $(READLINE_LDFLAGS)
PRODDIR_LDFLAGS += $(READLINE_LDFLAGS)
endif

View File

@@ -21,13 +21,15 @@ STATIC_LDFLAGS_YES= -Wl,-Bstatic
STATIC_LDFLAGS_NO=
STATIC_LDLIBS_YES= -Wl,-Bdynamic
# Set runtime path for shared libraries
SHRLIBDIR_RPATH_LDFLAGS_YES += $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
SHRLIBDIR_LDFLAGS += $(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Set runtime path for shared libraries if USE_RPATH=YES and STATIC_BUILD=NO
SHRLIBDIR_RPATH_LDFLAGS_YES_NO = $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath,%)
SHRLIBDIR_LDFLAGS += \
$(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
# Set runtime path for products
PRODDIR_RPATH_LDFLAGS_YES += $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
PRODDIR_LDFLAGS += $(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Set runtime path for products if USE_RPATH=YES and STATIC_BUILD=NO
PRODDIR_RPATH_LDFLAGS_YES_NO = $(PROD_DEPLIB_DIRS:%=-Wl,-rpath,%)
PRODDIR_LDFLAGS += \
$(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
# Link libraries controlled by COMMANDLINE_LIBRARY
# The newest Linux versions only need readline, older ones need both

View File

@@ -122,20 +122,10 @@ GNU_DIR_6 = $(WIND_BASE)/gnu/$(VX_GNU_VERSION)-vxworks-$(VXWORKS_VERSION)/$(WIND
GNU_DIR = $(GNU_DIR_$(VXWORKS_MAJOR_VERSION))
#--------------------------------------------------
# Wind River moved nm out of GNU_BIN in some versions
# This finds nm on any supported VxWorks version
WORKBENCH_BIN = $(WIND_BASE)/workbench-$(WORKBENCH_VERSION)/$(WIND_HOST_TYPE)/bin
UTILITIES_BIN = $(WIND_BASE)/utilities-$(UTILITIES_VERSION)/$(WIND_HOST_TYPE)/bin
NM_DIR_6.4 = $(WORKBENCH_BIN)
NM_DIR_6.5 = $(WORKBENCH_BIN)
NM_DIR_6.6 = $(WORKBENCH_BIN)
NM_DIR_6.7 = $(GNU_BIN)
NM_DIR_6.8 = $(UTILITIES_BIN)
NM_DIR_6.9 = $(UTILITIES_BIN)
NM_DIR = $(firstword $(NM_DIR_$(VXWORKS_VERSION)) $(GNU_BIN))
NM = $(NM_DIR)/$(CMPLR_PREFIX)nm$(CMPLR_SUFFIX)$(HOSTEXE)
NMPROG = $(CMPLR_PREFIX)nm$(CMPLR_SUFFIX)$(HOSTEXE)
NM = $(firstword $(wildcard $(WIND_BASE)/*/$(WIND_HOST_TYPE)/bin/$(NMPROG)))
#--------------------------------------------------
# A linker script is essential for munching from vxWorks 6.6 onwards
@@ -146,14 +136,10 @@ MUNCH_LDFLAGS_6 = -T $(VX_DIR)/target/h/tool/gnu/ldscripts/link.OUT
MUNCH_LDFLAGS = $(MUNCH_LDFLAGS_$(VXWORKS_MAJOR_VERSION))
#--------------------------------------------------
# The follow 2 exports prevent gnu cross-compiler
# from finding wrong assembler (as).
# These are required by some of the Wind River tools
export WIND_BASE
export WIND_HOME = $(WIND_BASE)
export WIND_HOST_TYPE
#--------------------------------------------------
# Tornado2.2
# The follow export allows vxWorks.h to include gnu header files
export TOOL_FAMILY = GNU
#--------------------------------------------------
@@ -196,6 +182,8 @@ OSITHREAD_USE_DEFAULT_STACK = NO
#--------------------------------------------------
# Link definitions
CROSS_LDFLAGS =
#
LINK.cpp = $(LD) -o $@ $(STATIC_LDFLAGS) $(PRODDIR_LDFLAGS) $(LDFLAGS)
LINK.cpp += $(PROD_LDFLAGS) $(PROD_LD_OBJS) $(PROD_LD_RESS) $(PROD_LDLIBS)

View File

@@ -11,19 +11,14 @@ GNU_TARGET = arm-linux
CMPLR_SUFFIX =
CMPLR_PREFIX = $(addsuffix -,$(GNU_TARGET))
# Provide a link-time path for shared libraries
SHRLIBDIR_RPATH_LDFLAGS_YES += $(SHRLIB_DEPLIB_DIRS:%=-Wl,-rpath-link,%)
SHRLIBDIR_LDFLAGS += $(SHRLIBDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Provide a link-time path for products
PRODDIR_RPATH_LDFLAGS_YES += $(PROD_DEPLIB_DIRS:%=-Wl,-rpath-link,%)
PRODDIR_LDFLAGS += $(PRODDIR_RPATH_LDFLAGS_$(LINKER_USE_RPATH))
# Provide a link-time path for readline
RUNTIME_LDFLAGS_READLINE_YES = -Wl,-rpath-link,$(GNU_DIR)/lib
RUNTIME_LDFLAGS_READLINE = $(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH))
RUNTIME_LDFLAGS_READLINE_CURSES = $(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH))
RUNTIME_LDFLAGS_READLINE_NCURSES = $(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH))
# Provide a link-time path for readline if needed
OP_SYS_INCLUDES += $(READLINE_DIR:%=-I%/include)
READLINE_LDFLAGS = $(READLINE_DIR:%=-L%/lib)
RUNTIME_LDFLAGS_READLINE_YES_NO = $(READLINE_DIR:%=-Wl,-rpath,%/lib)
RUNTIME_LDFLAGS += \
$(RUNTIME_LDFLAGS_READLINE_$(LINKER_USE_RPATH)_$(STATIC_BUILD))
SHRLIBDIR_LDFLAGS += $(READLINE_LDFLAGS)
PRODDIR_LDFLAGS += $(READLINE_LDFLAGS)
# Library flags
STATIC_LDFLAGS_YES= -Wl,-Bstatic

View File

@@ -1,10 +1,4 @@
# CONFIG_SITE.Common.linux-xscale_be
#
# Site specific definitions for linux-xscale_be target builds.
# Site specific definitions for all linux-xscale_be target builds.
#-------------------------------------------------------
# Set GNU_DIR to point to directory containing the tool-chain
# APS:
GNU_DIR = /usr/local/vw/xscale_be

View File

@@ -10,7 +10,7 @@
# Note: vxWorks 5.3 (Tornado 1.x) is not supported
#VXWORKS_VERSION = 5.4
VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 6.0
#VXWORKS_VERSION = 6.1
#VXWORKS_VERSION = 6.2
@@ -20,7 +20,7 @@ VXWORKS_VERSION = 5.5
#VXWORKS_VERSION = 6.6
#VXWORKS_VERSION = 6.7
#VXWORKS_VERSION = 6.8
#VXWORKS_VERSION = 6.9
VXWORKS_VERSION = 6.9
# Sites may override the following path for a particular host
@@ -31,19 +31,6 @@ VXWORKS_VERSION = 5.5
# Under vxWorks 6.x this is *not* the same as the old VX_DIR setting
#WIND_BASE = /usr/local/vw/tornado202p1
WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
#WIND_BASE = /usr/local/vw/vxWorks-$(VXWORKS_VERSION)
#WIND_BASE = /usr/local/vw/tornado22-$(ARCH_CLASS)
WIND_BASE = /usr/local/vw/vxWorks-$(VXWORKS_VERSION)
#WIND_BASE = /ade/vxWorks/$(VXWORKS_VERSION)
# WorkBench Version number, required for vxWorks 6.x
#WORKBENCH_VERSION = 2.6
#WORKBENCH_VERSION = 3.0
#WORKBENCH_VERSION = 3.2
#WORKBENCH_VERSION = 3.3
# Utilities Version number, required from vxWorks 6.8 and later
#UTILITIES_VERSION = 1.0

View File

@@ -7,8 +7,25 @@
GNU_TARGET = arm-xilinx-linux-gnueabi
# Set GNU tools install path
# This is the install path at APS:
# Examples are installations at the APS:
GNU_DIR = /usr/local/vw/zynq-2011.09
#GNU_DIR = /usr/local/Xilinx/SDK/2016.3/gnu/arm/lin
#GNU_DIR = /APSshare/XilinxSDK/2015.4/gnu/arm/lin
# If cross-building shared libraries and the paths on the target machine are
# different than on the build host, you should uncomment the lines below to
# disable putting runtime library paths in products and shared libraries.
# You will also need to provide another way for programs to find their shared
# libraries at runtime, such as by setting LD_LIBRARY_PATH or by using
# mechanisms related to /etc/ld.so.conf
#SHRLIBDIR_RPATH_LDFLAGS_YES_NO =
#PRODDIR_RPATH_LDFLAGS_YES_NO =
# Note: It may be simpler to just set STATIC_BUILD=YES here and not
# try to use shared libraries at all in these circumstances.
# To use libreadline, point this to its install prefix
#READLINE_DIR = $(GNU_DIR)
#READLINE_DIR = /tools/cross/linux-x86.linux-arm/readline
# See CONFIG_SITE.Common.linux-arm for other COMMANDLINE_LIBRARY values
#COMMANDLINE_LIBRARY = READLINE
# With a Xilinx SDK, it'll be something like
#GNU_DIR = /usr/local/zynq/Xilinx/SDK/2015.4/gnu/arm/lin

View File

@@ -0,0 +1,11 @@
# CONFIG_SITE.linux-x86.linux-xscale_be
#
# Site specific definitions for linux-x86 host - linux-xscale_be targets
#-------------------------------------------------------
# Set GNU_DIR to point to directory containing the tool-chain
GNU_DIR = /usr/local/vw/xscale_be
# If readline is available, configure it
READLINE_DIR = $(GNU_DIR)/target/usr
COMMANDLINE_LIBRARY = READLINE

View File

@@ -0,0 +1,7 @@
# CONFIG_SITE.linux-x86_64.linux-xscale_be
#
# Site specific settings for linux-x86_64 host - linux-xscale_be target
#-------------------------------------------------------
# Inherit setting from linux-x86
include $(CONFIG)/os/CONFIG_SITE.linux-x86.linux-xscale_be

View File

@@ -13,6 +13,50 @@
<!-- Insert new items immediately below here ... -->
<h3>Extend maximum Posix epicsEventWaitWithTimeout() delay</h3>
<p>The Posix implementation of epicsEventWaitWithTimeout() was limiting the
timeout delay to at most 60 minutes (3600.0 seconds). This has been changed to
10 years; significantly longer maximum delays cause problems on systems where
<tt>time_t</tt> is still a signed 32-bit integer so cannot represent absolute
time-stamps after 2038-01-19. Our assumption is that such 32-bit systems will
have been retired before the year 2028, but some additional tests have been
added to the epicsTimeTest program to detect and fail if this assumption is
violated.</p>
<h3>New test-related make targets</h3>
<p>This release adds several new make targets intended for use by developers
and Continuous Integration systems which simplify the task of running the
built-in self-test programs and viewing the results. Since these targets are
intended for limited use they can have requirements for the build host which
go beyond the standard minimum set needed to build and run Base.</p>
<blockquote>
<h4><tt>test-results</tt> &mdash; Summarize test results</h4>
<p>The new make target <tt>test-results</tt> will run the self-tests if
necessary to generate a TAP file for each test, then summarizes the TAP output
files in each test directory in turn, displaying the details of any failures.
This step uses the program <q>prove</q> which comes with Perl, but also needs
<q>cat</q> to be provided in the default search path so will not work on most
Windows systems.</p>
<h4><tt>junitfiles</tt> &mdash; Convert test results to JUnit XML Format</h4>
<p>The new make target <tt>junitfiles</tt> will run the self-tests if necessary
and then convert the TAP output files into the more commonly-supported JUnit
XML format. The program that performs this conversion needs the Perl module
<q><tt>XML::Generator</tt></q> to have been installed.</p>
<h4><tt>clean-tests</tt> &mdash; Delete test result files</h4>
<p>The new make target <tt>clean-tests</tt> removes any test result files from
previous test runs. It cleans both TAP and JUnit XML files.</p>
</blockquote>
<h3>Fix DNS related crash on exit</h3>
<p>The attempt to fix DNS related delays for short lived CLI programs (eg. caget)

View File

@@ -2746,7 +2746,7 @@ time.</p>
</dl>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Optional address of the user's callback function to be run when the
<dd>Optional pointer to the user's callback function to be run when the
connection state changes. Casual users of channel access may decide to
set this field to null or 0 if they do not need to have a callback
function run in response to each connection state change event.
@@ -2921,7 +2921,7 @@ but they do not cause the record to be processed.</p>
</dl>
<dl>
<dt><code>PFUNC</code></dt>
<dd>address of <a href="#User">user supplied callback function</a> to be
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
run when the requested operation completes</dd>
</dl>
<dl>
@@ -3029,7 +3029,7 @@ when a CA get request is initiated.</p>
</dl>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Address of <a href="#User">user supplied callback function</a> to be
<dd>Pointer to a <a href="#User">user supplied callback function</a> to be
run when the requested operation completes.</dd>
</dl>
<dl>
@@ -3130,8 +3130,8 @@ indicating the current state of the channel.</p>
<dd>channel identifier</dd>
</dl>
<dl>
<dt><code>USRERFUNC</code></dt>
<dd>The address of <a href="#User">user supplied callback function</a> to
<dt><code>USERFUNC</code></dt>
<dd>Pointer to a <a href="#User">user supplied callback function</a> to
be invoked with each subscription update.</dd>
</dl>
<dl>
@@ -3429,7 +3429,7 @@ field should not be used.</p>
<h4>Arguments</h4>
<dl>
<dt><code>USERFUNC</code></dt>
<dd>Address of user callback function to be executed when an exceptions
<dd>Pointer to a user callback function to be executed when exceptions
occur. Passing a null value causes the default exception handler to be
reinstalled. The following structure is passed by value to the user's
callback function. Currently, the <code>op</code> field can be one of
@@ -3564,7 +3564,7 @@ default handler uses fprintf to send messages to 'stderr'.</p>
<h4>Arguments</h4>
<dl>
<dt><code>PFUNC</code></dt>
<dd>The address of a user supplied callback handler to be invoked when CA
<dd>A pointer to a user supplied callback handler to be invoked when CA
prints diagnostic messages. Installing a null pointer will cause the
default callback handler to be reinstalled.</dd>
</dl>
@@ -3612,7 +3612,7 @@ specified channel.</p>
</dl>
<dl>
<dt><code>PFUNC</code></dt>
<dd>Address of user supplied callback function. A null pointer uninstalls
<dd>Pointer to a user supplied callback function. A null pointer uninstalls
the current handler. The following arguments are passed <em>by value</em>
to the supplied callback handler.
<pre>typedef struct ca_access_rights {

View File

@@ -74,10 +74,9 @@ LIBSRCS += casStreamIO.cc
LIBSRCS += ipIgnoreEntry.cc
# There is a bug in some vxWorks compilers that these work around:
ifeq ($(VX_GNU_VERSION), 4.1.2)
casStreamOS_CXXFLAGS_vxWorks-ppc604_altivec = -O0
casStreamOS_CXXFLAGS_vxWorks-ppc604_long = -O0
casStreamOS_CXXFLAGS_vxWorks-ppc604 = -O0
ifeq ($(VXWORKS_VERSION)$(filter -mcpu=604,$(ARCH_DEP_CFLAGS)), 6.6-mcpu=604)
casDGIntfOS_CXXFLAGS = -fno-inline
casStreamOS_CXXFLAGS = -fno-inline
endif
LIBSRCS_vxWorks += templateInstances.cpp

View File

@@ -530,8 +530,20 @@ caStatus casStrmClient::readResponse ( epicsGuard < casClientMutex > & guard,
pChan->getCID(), status, ECA_GETFAIL );
}
aitUint32 elementCount = 0;
if (desc.isContainer()) {
aitUint32 index;
int gdds = gddApplicationTypeTable::app_table.mapAppToIndex
( desc.applicationType(), gddAppType_value, index );
if ( gdds ) {
return S_cas_badType;
}
elementCount = desc.getDD(index)->getDataSizeElements();
} else {
elementCount = desc.getDataSizeElements();
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
(ca_uint32_t)elementCount :
msg.m_count;
void * pPayload;
@@ -659,8 +671,20 @@ caStatus casStrmClient::readNotifyResponse ( epicsGuard < casClientMutex > & gua
return ecaStatus;
}
aitUint32 elementCount = 0;
if (desc.isContainer()) {
aitUint32 index;
int gdds = gddApplicationTypeTable::app_table.mapAppToIndex
( desc.applicationType(), gddAppType_value, index );
if ( gdds ) {
return S_cas_badType;
}
elementCount = desc.getDD(index)->getDataSizeElements();
} else {
elementCount = desc.getDataSizeElements();
}
ca_uint32_t count = (msg.m_count == 0) ?
(ca_uint32_t)desc.getDataSizeElements() :
(ca_uint32_t)elementCount :
msg.m_count;
void *pPayload;

View File

@@ -81,14 +81,14 @@ static void sprint_long (char *ret, dbr_long_t val, IntFormatT outType)
}
else {
const char *fmt[4] = { /* Order must match the enum IntFormatT */
"%ld" /* dec */,
"0" /* bin, val is 0 */,
"0o%lo" /* oct */,
"0x%lX" /* hex */
"%d" /* dec */,
"0" /* bin and val is 0 */,
"0o%o" /* oct */,
"0x%X" /* hex */
};
/* Formats have long modifier, pass value as a long */
sprintf(ret, fmt[outType], (long) val);
/* dbr_long_t is actually an int on all supported platforms */
sprintf(ret, fmt[outType], (int) val);
}
}

View File

@@ -60,6 +60,10 @@ static void *exitCallback;
static char *threadName[NUM_CALLBACK_PRIORITIES] = {
"cbLow", "cbMedium", "cbHigh"
};
#define FULL_MSG(name) "callbackRequest: " name " ring buffer full\n"
static char *fullMessage[NUM_CALLBACK_PRIORITIES] = {
FULL_MSG("cbLow"), FULL_MSG("cbMedium"), FULL_MSG("cbHigh")
};
static unsigned int threadPriority[NUM_CALLBACK_PRIORITIES] = {
epicsThreadPriorityScanLow - 1,
epicsThreadPriorityScanLow + 4,
@@ -168,11 +172,7 @@ void callbackRequest(CALLBACK *pcallback)
epicsInterruptUnlock(lockKey);
if (!pushOK) {
char msg[48] = "callbackRequest: ";
strcat(msg, threadName[priority]);
strcat(msg, " ring buffer full\n");
epicsInterruptContextMessage(msg);
epicsInterruptContextMessage(fullMessage[priority]);
ringOverflow[priority] = TRUE;
}
epicsEventSignal(callbackSem[priority]);

View File

@@ -116,7 +116,7 @@ epicsShareFunc void fdManager::process (double delay)
if ( ioPending ) {
struct timeval tv;
tv.tv_sec = static_cast<long> ( minDelay );
tv.tv_sec = static_cast<time_t> ( minDelay );
tv.tv_usec = static_cast<long> ( (minDelay-tv.tv_sec) * uSecPerSec );
fd_set * pReadSet = & this->fdSetsPtr[fdrRead];

View File

@@ -67,14 +67,14 @@ convertDoubleToWakeTime(double timeout, struct timespec *wakeTime)
mach_timespec_t now;
struct timespec wait;
if (timeout < 0.0)
timeout = 0.0;
else if (timeout > 60 * 60 * 24 * 3652.5)
timeout = 60 * 60 * 24 * 3652.5; /* 10 years */
clock_get_time(host_clock, &now);
if (timeout<0.0)
timeout = 0.0;
else if(timeout>3600.0)
timeout = 3600.0;
wait.tv_sec = static_cast< long >(timeout);
wait.tv_sec = static_cast< time_t >(timeout);
wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9);
wakeTime->tv_sec = now.tv_sec + wait.tv_sec;

View File

@@ -87,30 +87,35 @@ int epicsTime_localtime ( const time_t *clock, // X aCC 361
extern "C" epicsShareFunc void
convertDoubleToWakeTime(double timeout,struct timespec *wakeTime)
{
struct timespec wait;
struct timespec now, wait;
int status;
if(timeout<0.0) timeout = 0.0;
else if(timeout>3600.0) timeout = 3600.0;
if (timeout < 0.0)
timeout = 0.0;
else if (timeout > 60 * 60 * 24 * 3652.5)
timeout = 60 * 60 * 24 * 3652.5; /* 10 years */
#ifdef CLOCK_REALTIME
status = clock_gettime(CLOCK_REALTIME, wakeTime);
status = clock_gettime(CLOCK_REALTIME, &now);
#else
{
struct timeval tv;
struct timezone tz;
status = gettimeofday(&tv, &tz);
wakeTime->tv_sec = tv.tv_sec;
wakeTime->tv_nsec = tv.tv_usec * 1000;
now.tv_sec = tv.tv_sec;
now.tv_nsec = tv.tv_usec * 1000;
}
#endif
if (status) {
perror("convertDoubleToWakeTime");
cantProceed("convertDoubleToWakeTime");
}
wait.tv_sec = static_cast< long >(timeout);
wait.tv_sec = static_cast< time_t >(timeout);
wait.tv_nsec = static_cast< long >((timeout - (double)wait.tv_sec) * 1e9);
wakeTime->tv_sec += wait.tv_sec;
wakeTime->tv_nsec += wait.tv_nsec;
wakeTime->tv_sec = now.tv_sec + wait.tv_sec;
wakeTime->tv_nsec = now.tv_nsec + wait.tv_nsec;
if (wakeTime->tv_nsec >= 1000000000L) {
wakeTime->tv_nsec -= 1000000000L;
++wakeTime->tv_sec;

View File

@@ -48,7 +48,7 @@ MAIN(epicsTimeTest)
const int wasteTime = 100000;
const int nTimes = 10;
testPlan(15 + nTimes * 19);
testPlan(17 + nTimes * 19);
try {
const epicsTimeStamp epochTS = {0, 0};
@@ -216,5 +216,35 @@ MAIN(epicsTimeTest)
testOk1(beginTS + diff == now);
}
epicsTime ten_years_hence;
try {
now = epicsTime::getCurrent();
ten_years_hence = now + 60 * 60 * 24 * 3652.5;
testPass("epicsTime can represent 10 years hence");
}
catch ( ... ) {
testFail("epicsTime exception for value 10 years hence");
}
try {
/* This test exists because in libCom/osi/os/posix/osdTime.cpp
* the convertDoubleToWakeTime() routine limits the timeout delay
* to 10 years. libCom/timer/timerQueue.cpp returns DBL_MAX for
* queues with no timers present, and convertDoubleToWakeTime()
* has to return an absolute Posix timestamp. On 2028-01-19 any
* systems that still implement time_t as a signed 32-bit integer
* will be unable to represent that timestamp, so this will fail.
*/
time_t_wrapper os_time_t = ten_years_hence;
epicsTime then = os_time_t; // No fractional seconds
double delta = ten_years_hence - then;
testOk(delta >= 0 && delta < 1.0,
"OS time_t can represent 10 years hence");
}
catch ( ... ) {
testFail("OS time_t conversion exception for value 10 years hence");
}
return testDone();
}

View File

@@ -74,13 +74,13 @@ void testTimer (fdctx *pfdm, double delay)
epicsTimeGetCurrent (&begin);
cbs.done = 0;
tmo.tv_sec = (unsigned long) delay;
tmo.tv_sec = (time_t) delay;
tmo.tv_usec = (unsigned long) ((delay - tmo.tv_sec) * uSecPerSec);
aid = fdmgr_add_timeout (pfdm, &tmo, alarmCB, &cbs);
verify (aid!=fdmgrNoAlarm);
while (!cbs.done) {
tmo.tv_sec = (unsigned long) delay;
tmo.tv_sec = (time_t) delay;
tmo.tv_usec = (unsigned long) ((delay - tmo.tv_sec) * uSecPerSec);
status = fdmgr_pend_event (pfdm, &tmo);
verify (status==0);

View File

@@ -107,7 +107,7 @@ private:
epicsTime exceptMsgTimeStamp;
bool cancelPending;
static const double exceptMsgMinPeriod;
void printExceptMsg ( const char * pName,
void printExceptMsg ( const char * pName,
const type_info & type );
timerQueue ( const timerQueue & );
timerQueue & operator = ( const timerQueue & );

View File

@@ -43,6 +43,9 @@ include "devSoft.dbd"
registrar(asSub)
variable(asCaDebug,int)
# CA server debug flag (very verbose) range[0,5]
variable(CASDEBUG,int)
# dbStaticLib settings
variable(dbRecordsOnceOnly,int)
variable(dbBptNotMonotonic,int)

View File

@@ -207,6 +207,14 @@ static long init_record(aSubRecord *prec, int pass)
}
strcpy(prec->onam, prec->snam);
prec->oval = prec->val;
for (i = 0; i < NUM_ARGS; i++) {
epicsUInt32 nev = (&prec->neva)[i];
(&prec->onva)[i] = nev;
if (nev)
memcpy((&prec->ovla)[i], (&prec->vala)[i],
dbValueSize((&prec->ftva)[i]) * nev);
}
return 0;
}

View File

@@ -216,10 +216,10 @@ va_list args
/*
* add their context string into the protocol
*/
localStatus = epicsVsnprintf ( pMsgString, maxDiagLen, pformat, args );
localStatus = epicsVsnprintf ( pMsgString, maxDiagLen - size, pformat, args );
if ( localStatus >= 1 ) {
unsigned diagLen = ( unsigned ) localStatus;
if ( diagLen < maxDiagLen ) {
if ( diagLen < maxDiagLen - size ) {
size += (ca_uint32_t) (diagLen + 1u);
}
else {
@@ -227,7 +227,7 @@ va_list args
"caserver: vsend_err: epicsVsnprintf detected "
"error message truncation, pFormat = \"%s\"\n",
pformat );
size += maxDiagLen;
size = maxDiagLen;
pMsgString [ maxDiagLen - 1 ] = '\0';
}
}
@@ -2528,8 +2528,10 @@ int camessage ( struct client *client )
* aligned payloads
*/
if ( msgsize & 0x7 ) {
SEND_LOCK(client);
send_err ( &msg, ECA_INTERNAL, client,
"CAS: Missaligned protocol rejected" );
SEND_UNLOCK(client);
log_header ( "CAS: Missaligned protocol rejected",
client, &msg, 0, nmsg );
status = RSRV_ERROR;
@@ -2545,9 +2547,11 @@ int camessage ( struct client *client )
if ( msgsize > client->recv.maxstk ) {
casExpandRecvBuffer ( client, msgsize );
if ( msgsize > client->recv.maxstk ) {
SEND_LOCK(client);
send_err ( &msg, ECA_TOLARGE, client,
"CAS: Server unable to load large request message. Max bytes=%lu",
rsrvSizeofLargeBufTCP );
SEND_UNLOCK(client);
log_header ( "CAS: server unable to load large request message",
client, &msg, 0, nmsg );
assert ( client->recv.cnt <= client->recv.maxstk );

View File

@@ -41,30 +41,18 @@
void camsgtask ( void *pParm )
{
struct client *client = (struct client *) pParm;
int nchars;
int status;
casAttachThreadToClient ( client );
/*
* send the server's minor version number to the client
*/
status = cas_copy_in_header ( client, CA_PROTO_VERSION, 0,
0, CA_MINOR_PROTOCOL_REVISION, 0, 0, 0 );
if ( status != ECA_NORMAL ) {
LOCK_CLIENTQ;
ellDelete ( &clientQ, &client->node );
UNLOCK_CLIENTQ;
destroy_tcp_client ( client );
return;
}
while (castcp_ctl == ctlRun && !client->disconnect) {
osiSockIoctl_t check_nchars;
long nchars;
int status;
/*
* allow message to batch up if more are comming
*/
status = socket_ioctl (client->sock, FIONREAD, &nchars);
status = socket_ioctl (client->sock, FIONREAD, &check_nchars);
if (status < 0) {
char sockErrBuf[64];
@@ -74,7 +62,7 @@ void camsgtask ( void *pParm )
sockErrBuf);
cas_send_bs_msg(client, TRUE);
}
else if (nchars == 0){
else if (check_nchars == 0){
cas_send_bs_msg(client, TRUE);
}
@@ -150,6 +138,9 @@ void camsgtask ( void *pParm )
}
else {
char buf[64];
/* flush any queued messages before shutdown */
cas_send_bs_msg(client, 1);
client->recv.cnt = 0ul;

View File

@@ -37,11 +37,18 @@
* cas_send_bs_msg()
*
* (channel access server send message)
*
*
* Set lock_needed=1 unless SEND_LOCK() is held by caller
*/
void cas_send_bs_msg ( struct client *pclient, int lock_needed )
{
int status;
if ( lock_needed ) {
SEND_LOCK ( pclient );
}
if ( CASDEBUG > 2 && pclient->send.stk ) {
errlogPrintf ( "CAS: Sending a message of %d bytes\n", pclient->send.stk );
}
@@ -52,13 +59,11 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed )
pclient->sock, (unsigned) pclient->addr.sin_addr.s_addr );
}
pclient->send.stk = 0u;
if(lock_needed)
SEND_UNLOCK(pclient);
return;
}
if ( lock_needed ) {
SEND_LOCK ( pclient );
}
while ( pclient->send.stk && ! pclient->disconnect ) {
status = send ( pclient->sock, pclient->send.buf, pclient->send.stk, 0 );
if ( status >= 0 ) {

View File

@@ -241,7 +241,6 @@ int rsrv_init (void)
clientQlock = epicsMutexMustCreate();
ellInit ( &clientQ );
freeListInitPvt ( &rsrvClientFreeList, sizeof(struct client), 8 );
freeListInitPvt ( &rsrvChanFreeList, sizeof(struct channel_in_use), 512 );
freeListInitPvt ( &rsrvEventFreeList, sizeof(struct event_ext), 512 );
@@ -951,16 +950,22 @@ struct client *create_tcp_client ( SOCKET sock )
void casStatsFetch ( unsigned *pChanCount, unsigned *pCircuitCount )
{
LOCK_CLIENTQ;
if ( ! clientQlock ) {
*pCircuitCount = 0;
*pChanCount = 0;
return;
}
LOCK_CLIENTQ;
{
int circuitCount = ellCount ( &clientQ );
if ( circuitCount < 0 ) {
*pCircuitCount = 0;
*pCircuitCount = 0;
}
else {
*pCircuitCount = (unsigned) circuitCount;
*pCircuitCount = (unsigned) circuitCount;
}
*pChanCount = rsrvChannelCount;
}
UNLOCK_CLIENTQ;
UNLOCK_CLIENTQ;
}

View File

@@ -7,11 +7,15 @@
* in file LICENSE that is included with this distribution.
\*************************************************************************/
#include "osiSock.h"
#include "iocsh.h"
#define epicsExportSharedSymbols
#include "rsrv.h"
#include "server.h"
#include "rsrvIocRegister.h"
#include "epicsExport.h"
/* casr */
static const iocshArg casrArg0 = { "level",iocshArgInt};
static const iocshArg * const casrArgs[1] = {&casrArg0};
@@ -21,8 +25,9 @@ static void casrCallFunc(const iocshArgBuf *args)
casr(args[0].ival);
}
void epicsShareAPI rsrvIocRegister(void)
{
iocshRegister(&casrFuncDef,casrCallFunc);
}
epicsExportAddress(int, CASDEBUG);

View File

@@ -62,8 +62,10 @@ typedef struct caHdrLargeArray {
enum messageBufferType { mbtUDP, mbtSmallTCP, mbtLargeTCP };
struct message_buffer {
char *buf;
/*! points to first filled byte in buffer */
unsigned stk;
unsigned maxstk;
/*! points to first unused byte in buffer (after filled bytes) */
unsigned cnt;
enum messageBufferType type;
};
@@ -72,7 +74,9 @@ extern epicsThreadPrivateId rsrvCurrentClient;
typedef struct client {
ELLNODE node;
/*! guarded by SEND_LOCK() aka. client::lock */
struct message_buffer send;
/*! accessed by receive thread w/o locks cf. camsgtask() */
struct message_buffer recv;
epicsMutexId lock;
epicsMutexId putNotifyLock;
@@ -156,7 +160,7 @@ enum ctl {ctlInit, ctlRun, ctlPause, ctlExit};
/* NOTE: external used so they remember the state across loads */
#ifdef GLBLSOURCE
# define GLBLTYPE
# define GLBLTYPE_INIT(A)
# define GLBLTYPE_INIT(A) = A
#else
# define GLBLTYPE extern
# define GLBLTYPE_INIT(A)
@@ -176,7 +180,7 @@ GLBLTYPE int CASDEBUG;
GLBLTYPE SOCKET IOC_sock;
GLBLTYPE SOCKET IOC_cast_sock;
GLBLTYPE unsigned short ca_server_port;
GLBLTYPE ELLLIST clientQ; /* locked by clientQlock */
GLBLTYPE ELLLIST clientQ GLBLTYPE_INIT(ELLLIST_INIT);
GLBLTYPE ELLLIST beaconAddrList;
GLBLTYPE epicsMutexId clientQlock;
GLBLTYPE struct client *prsrv_cast_client;

View File

@@ -29,6 +29,7 @@ PERL_SCRIPTS += makeTestfile.pl
PERL_SCRIPTS += mkmf.pl
PERL_SCRIPTS += munch.pl
PERL_SCRIPTS += replaceVAR.pl
PERL_SCRIPTS += tap-to-junit-xml.pl
PERL_SCRIPTS += useManifestTool.pl
include $(TOP)/configure/RULES

View File

@@ -0,0 +1,546 @@
#!/usr/local/bin/perl
=head1 NAME
tap-to-junit-xml - convert perl-style TAP test output to JUnit-style XML
=head1 SYNOPSIS
tap-to-junit-xml [--help|--man]
[--[no]hidesummary]
[--input <tap input file>]
[--output <junit output file>]
[--puretap]
[<test suite name>] [outputprefix]
=head1 DESCRIPTION
Parse test suite output in TAP (Test Anything Protocol,
C<http://testanything.org/>) format, and produce XML output in a similar format
to that produced by the <junit> ant task. This is useful for consumption by
continuous-integration systems like Hudson (C<https://hudson.dev.java.net/>).
C<"test suite name"> is a descriptive string used as the B<name> attribute on the
top-level <testsuites> node of the output XML. Defaults to "make test".
If C<outputprefix> is specified, multi-file output will be generated, with
multiple XML files created using C<outputprefix> as the start of their
filenames. The files are separated by testplan. This option is ignored
if --puretap is specified (TAP only allows one testplan per input file).
This prefix may contain slashes, in which case the files will be
placed into a directory hierarchy accordingly (although care should be taken to
ensure these directories exist in advance).
If --input I<file name> is not specified, STDIN will be read.
If C<outputprefix> or --output is not specified, a single XML file will be
generated on STDOUT.
--output I<file name> is used to write a single XML file to I<file name>.
--puretap parses a single TAP source and handles parse errors and directives
(todo, skip, bailout). --puretap ignores unknown (non-TAP) input. Without
--puretap, the script will parse some additional non-TAP test input, such as
Perl tests that can include a "Test Summary Report", but it won't generate
correct XML unless the TAP testplan comes before the test cases.
--hidesummary report (the default) will hide the summary report, --no-hidesummary
will display it (neither has an effect when --puretap is specified).
=head1 EXAMPLE
prove -v 2>&1 | tee tests.log
tap-to-junit-xml "make test" testxml/tests < tests.log
(JUnit-formatted XML is now in "testxml/tests*.xml".)
=head1 DEPENDENCIES
Getopt::Long
Pod::Usage
TAP::Parser
Time::HiRes
XML::Generator
=head1 BUGS
- Output is optimized for Hudson, and may not look quite as good in
other UIs.
- Doesn't do anything with the STDERR from tests.
- Doesn't fill in the 'errors' attribute in the <testsuite> element.
(--puretap handles parse errors)
- Doesn't handle "todo" or "skip" (--puretap does)
- Doesn't get the elapsed time for each 'test' (i.e. assertion.)
(TAP output has no elapsed time convention).
=head1 SOURCE
http://github.com/jmason/tap-to-junit-xml/tree/master
=head1 AUTHOR
original, junit_xml.pl, by Matisse Enzer <matisse at matisse.net>; see
C<http://twoalpha.blogspot.com/2007/01/junit-style-xml-from-perl-test-files.html>.
pretty much entirely rewritten by Justin Mason <junit at jmason.org>, Feb 2008.
Miscellaneous fixes and mods (--puretap) by Jascha Lee <jascha at yahoo-inc.com>, Mar 2009.
=head1 VERSION
Mar 27 2008 jm
Mar 17 2009 jl
=head1 COPYRIGHT & LICENSE
Copyright (c) 2007 Matisse Enzer. All Rights Reserved.
This program is free software; you can redistribute it and/or modify it
under the same terms as Perl itself.
=cut
use strict;
use warnings;
use Getopt::Long qw(:config no_ignore_case);
use Pod::Usage;
use TAP::Parser;
use Time::HiRes qw(gettimeofday tv_interval);
use XML::Generator qw(:noimport);
my %opts;
pod2usage() unless GetOptions( \%opts, 'help|h',
'hidesummary!',
'input=s',
'man',
'output=s',
'puretap'
);
pod2usage(-verbose => 1) if defined $opts{'help'};
pod2usage(-verbose => 2) if defined $opts{'man'};
my $opt_suitename = shift @ARGV;
my $opt_multifile = 0;
my $opt_mfprefix;
if (defined $ARGV[0]) {
$opt_multifile = 1;
$opt_mfprefix = $ARGV[0];
}
# should the 'Test Summary Report' at the end of a test suite be displayed
# as if it was a testcase? in my opinion, no
my $HIDE_TEST_SUMMARY_REPORT = defined $opts{'hidesummary'} ? $opts{'hidesummary'} : 1;
my $suite_name = $opt_suitename || 'make test';
my $safe_suite_name = $suite_name; $safe_suite_name =~ s/[^-:_A-Za-z0-9]+/_/gs;
# TODO: it'd be nice to respect 'Universal desirable behavior #1' from
# http://testanything.org/wiki/index.php/TAP_Consumers -- 'Should work on the
# TAP as a stream (ie. as each line is received) rather than wait until all the
# TAP is received'. But it seems TAP::Parser itself doesn't support it!
# maybe when TAP::Parser does that, we'll do it too.
my $tapfh;
if ( defined $opts{'input'} ) {
open $tapfh, '<', $opts{'input'} or die "Can't open TAP file '$opts{'input'}': $!\n";
}
else {
$tapfh = \*STDIN;
}
my $outfh;
if ( defined $opts{'output'} ) {
open $outfh, '>', $opts{'output'} or die "Can't open output file '$opts{'output'}' for writing: $!\n";
}
else {
$outfh = \*STDOUT;
}
my $tap = TAP::Parser->new( { source => $tapfh } );
my $xmlgen = XML::Generator->new( ':pretty');
my $xmlgenunescaped = XML::Generator->new( escape => 'unescaped',
conformance => 'strict',
pretty => 2
);
my @properties = _get_properties($xmlgen);
if ( defined $opts{'puretap'} ) {
#
# Instead of trying to parse everything in one pass, which fails if the
# testplan is last, parse through the results for the test cases and
# then construct the <testsuite> information from the TAP and wrap it
# around the test cases. Ignore 'unknown' information. [JL]
#
my @testcases = _parse_testcases( $tap, $xmlgen );
errorOut( $tap, $xmlgen ) if $tap->parse_errors;
print $outfh $xmlgen->testsuites(
$xmlgen->testsuite( { name => $safe_suite_name,
tests => $tap->tests_planned,
failures => scalar $tap->failed,
errors => 0,
time => 0,
id => 1 },
@testcases ));
}
else {
my $test_results = _parse_tests( $tap, $xmlgen );
if ($opt_multifile) {
_gen_junit_multifile_xml( $xmlgen, \@properties, $test_results );
} else {
print $outfh _get_junit_xml( $xmlgen, \@properties, $test_results );
}
}
exit;
#-------------------------------------------------------------------------------
sub _get_junit_xml {
my ( $xmlgen, $properties, $test_results ) = @_;
my $xml = "<?xml version='1.0' encoding='UTF-8' ?>\n" .
$xmlgen->testsuites({
name => $suite_name,
}, @$test_results);
return $xml;
}
sub _gen_junit_multifile_xml {
my ( $xmlgen, $properties, $test_results ) = @_;
my $count = 1;
foreach my $testsuite (@$test_results) {
open OUT, ">${opt_mfprefix}.${count}.xml"
or die "cannot write ${opt_mfprefix}.${count}.xml";
print OUT "<?xml version='1.0' encoding='UTF-8' ?>\n";
print OUT $testsuite;
close OUT;
$count++;
}
}
#
# Wrap up parse errors and output them as test cases.
#
sub errorOut {
my $parser = shift;
my $xmlgen = shift;
die "errorOut() needs some args" unless $parser and $xmlgen;
my ($xml, @errors, $name);
my $count = 1;
foreach my $error ( $parser->parse_errors ) {
$name = sprintf "%s%02d", 'Error_', $count++;
$xml = $xmlgen->testcase( { name => $name,
classname => 'TestsNotRun.ParseError',
time => 0 },
$xmlgen->error( { type => 'TAPParseError',
message => $error } ));
push @errors, $xml;
}
print $outfh $xmlgen->testsuites(
$xmlgen->testsuite( { name => 'TestsNotRun.ParseError',
tests => $tap->tests_planned,
failures => 0,
errors => scalar $tap->parse_errors,
time => 0,
id => 1 },
@errors ));
exit 86;
}
#
# Construct an array of XML'd test cases
#
sub _parse_testcases {
my $parser = shift;
my $xmlgen = shift;
return () unless $parser and $xmlgen;
my ($name, $directive, $xml, @testcases);
while ( my $result = $parser->next ) {
if ( $result->is_bailout ) {
$xml = $xmlgen->testcase( { name => 'BailOut',
classname => "$safe_suite_name.Tests",
time => 0 },
$xmlgen->error( { type => 'BailOut',
message => $result->explanation } ));
push @testcases, $xml;
last;
}
next unless $result->is_test;
$directive = $result->directive;
$name = sprintf "%s%02d", 'Test_', $result->number;
$name .= "_$directive" if $directive;
if ( $result->is_ok ) {
$xml = $xmlgen->testcase( { name => $name,
classname => "$safe_suite_name.Tests",
time => 0 } );
push @testcases, $xml;
}
else {
$xml = $xmlgen->testcase( { name => $name,
classname => "$safe_suite_name.Tests",
time => 0 },
$xmlgen->failure( { type => 'TAPTestFailed',
message => $result->as_string } ));
push @testcases, $xml;
}
}
return @testcases;
}
sub _parse_tests {
my ( $parser, $xmlgen ) = @_;
my $ctx = {
testsuites => [ ],
test_name => 'notest',
plan_ntests => 0,
case_id => 0,
};
_new_ctx($ctx);
my $lastunk = '';
# unknown t/basic_lint.........
# plan 1..1
# comment # Running under perl version 5.008008 for linux
# comment # Current time local: Thu Jan 24 17:44:30 2008
# comment # Current time GMT: Thu Jan 24 17:44:30 2008
# comment # Using Test.pm version 1.25
# unknown /usr/bin/perl -T -w ../spamassassin.raw -C log/test_rules_copy --siteconfigpath log/localrules.tmp -p log/test_default.cf -L --lint
# unknown Checking anything
# test ok 1
# test ok 2
# unknown t/basic_meta.........
# plan 1..2
# comment # Running under perl version 5.008008 for linux
# comment # Current time local: Thu Jan 24 17:44:31 2008
# comment # Current time GMT: Thu Jan 24 17:44:31 2008
# comment # Using Test.pm version 1.25
# test not ok 1
# comment # Failed test 1 in t/basic_meta.t at line 91
# test ok 2
# unknown Failed 1/2 subtests
# unknown t/basic_obj_api......
# plan 1..4
# comment # Running under perl version 5.008008 for linux
# comment # Current time local: Thu Jan 24 17:44:33 2008
# comment # Current time GMT: Thu Jan 24 17:44:33 2008
# comment # Using Test.pm version 1.25
# test ok 1
# test ok 2
# test ok 3
# test ok 4
# test ok 9
# unknown
# unknown Test Summary Report
# unknown -------------------
# unknown t/basic_meta.t (Wstat: 0 Tests: 2 Failed: 1)
# unknown Failed test: 1
# unknown Files=3, Tests=7, 6 wallclock secs ( 0.01 usr 0.00 sys + 4.39 cusr 0.23 csys = 4.63 CPU)
# unknown Result: FAIL
# unknown Failed 1/3 test programs. 1/7 subtests failed.
# unknown make: *** [test_dynamic] Error 255
while ( my $r = $parser->next ) {
my $t = $r->type;
my $s = $r->as_string; $s =~ s/\s+$//;
# warn "JMD $t $s";
if ($t eq 'unknown') {
$lastunk = $s;
# PERL_DL_NONLAZY=1 /usr/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(1, 'blib/lib', 'blib/arch')" t/basic_*
# if ($s =~ /test_harness\(.*?\)" (.+)$/) {
# $suite_name = $1;
# }
if ($s =~ /^Test Summary Report$/) {
# create a <testsuite> block for the summary
$ctx->{plan_ntests} = 0;
$ctx->{test_name} = "Test Summary Report";
$ctx->{case_tests} = 1;
_finish_test_block($ctx);
}
elsif ($s =~ /^Result: FAIL$/) {
$ctx->{case_tests}++;
$ctx->{case_failures}++;
my $test_case = {
classname => test_name_to_classname($ctx->{test_name}),
name => 'result',
'time' => 0,
};
my $failure = $xmlgen->failure({
type => "OverallTestsFailed",
message => $s
}, "__FAILUREMESSAGETODO__");
if (!$HIDE_TEST_SUMMARY_REPORT) {
push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case, $failure);
}
}
elsif ($s =~ /^(\S+?)\.\.\.+1\.\.(\d+?)\s*$/) {
# perl 5.6.x "Test" format plan line
# unknown t/basic_lint....................1..1
my ($name, $nt) = ($1,$2);
if ($ctx->{plan_ntests}) { # only if there have been tests planned
_finish_test_block($ctx);
}
$ctx->{plan_ntests} = $nt+0;
$ctx->{test_name} = "$name.t";
}
}
elsif ($t eq 'plan') {
if ($ctx->{plan_ntests}) { # only if there have been tests planned
_finish_test_block($ctx);
}
$ctx->{plan_ntests} = 0;
$s =~ /(\d+)$/ and $ctx->{plan_ntests} = $1+0;
$ctx->{test_name} = $lastunk;
$ctx->{test_name} =~ s/\.*\s*$//gs;
$ctx->{test_name} .= ".t";
}
elsif ($t eq 'test') {
my $ntest = 0;
if ($s =~ /(?:not |)\S+ (\d+)/) { $ntest = $1+0; }
if ($ntest > $ctx->{plan_ntests}) {
# jump in test numbers, more than planned; this is probably TAP::Parser's wierdness.
# (when it sees the "ok" line at the end of a test case with no number,
# it outputs the current total number of tests so far.)
next;
}
# clean this up in a Hudson-compatible way; ":" and "/" are out, "." also causes
# trouble by creating an extra "directory" in the results
my $test_case = {
classname => test_name_to_classname($ctx->{test_name}),
name => sprintf("test %6d", $ntest), # space-padding ensures ordering
'time' => 0,
};
$ctx->{case_tests}++;
my $failure = undef;
if ($s =~ /^not /i) {
$ctx->{case_failures}++;
$failure = $xmlgen->failure({
type => "TAPTestFailed",
message => $s
}, "__FAILUREMESSAGETODO__");
push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case, $failure);
}
else {
push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case);
}
}
$ctx->{sysout} .= $s."\n";
}
if (scalar(@{$ctx->{test_cases}}) == 0 &&
scalar(@{$ctx->{testsuites}}) == 0)
{
# no tests found! create a <testsuite> block containing *something* at least
$ctx->{case_tests}++;
my $test_case = {
classname => test_name_to_classname($ctx->{test_name}),
name => 'result',
'time' => 0,
};
push @{$ctx->{test_cases}}, $xmlgen->testcase($test_case);
}
_finish_test_block($ctx);
return $ctx->{testsuites};
}
sub _new_ctx {
my $ctx = shift;
$ctx->{start_time} = [gettimeofday];
$ctx->{test_cases} = [];
$ctx->{case_tests} = 0;
$ctx->{case_failures} = 0;
$ctx->{case_time} = 0;
$ctx->{case_id}++;
$ctx->{sysout} = '';
return $ctx;
}
sub _finish_test_block {
my $ctx = shift;
$ctx->{sysout} =~ s/\n\S+\.*\s*\n$/\n/s; # remove next test's "t/foo....." line
my $elapsed_time = 0; # TODO
#my $elapsed_time = tv_interval( $ctx->{start_time}, [gettimeofday] );
# clean it up to valid Java packagename format (or at least something Hudson will
# consume)
my $name = $ctx->{test_name};
$name =~ s/[^-:_A-Za-z0-9]+/_/gs;
$name = "$safe_suite_name.$name"; # a "directory" for the suite name
my $testsuite = {
'time' => $elapsed_time,
'name' => $name,
tests => $ctx->{case_tests},
failures => $ctx->{case_failures},
'id' => $ctx->{case_id},
errors => 0,
};
my @fixedcases = ();
foreach my $tc (@{$ctx->{test_cases}}) {
if ($tc =~ s/__FAILUREMESSAGETODO__/ cdata($ctx->{sysout}) /ges) {
push @fixedcases, \$tc; # inhibits escaping!
} else {
push @fixedcases, $tc;
}
}
# use "unescaped"; we have already fixed escaping on these strings.
# note that a reference means 'this is unescaped', bizarrely.
push @{$ctx->{testsuites}}, $xmlgenunescaped->testsuite($testsuite,
@fixedcases,
\("<system-out>\n".cdata($ctx->{sysout})."\n</system-out>"),
\("<system-err />"));
_new_ctx($ctx);
};
sub cdata {
my $s = shift;
$s =~ s/\]\]>/\](warning: defanged by tap-to-junit-xml)\]>/gs;
return '<![CDATA['.$s.']]>';
}
sub _get_properties {
my $xmlgen = shift;
my @props;
foreach my $key ( sort keys %ENV ) {
push @props, $xmlgen->property( { name => "$key", value => $ENV{$key} } );
}
return @props;
}
sub test_name_to_classname {
my $safe = shift;
$safe =~ s/[^-:_A-Za-z0-9]+/_/gs;
$safe = "$safe_suite_name.$safe"; # a "directory" for the suite name
$safe;
}
__END__
# JUnit references:
# http://www.nabble.com/JUnit-4-XML-schematized--td13946472.html
# http://jra1mw.cvs.cern.ch:8180/cgi-bin/jra1mw.cgi/org.glite.testing.unit/config/JUnitXSchema.xsd?view=markup
# skipped tests:
# https://hudson.dev.java.net/issues/show_bug.cgi?id=1251
# Hudson source:
# http://fisheye5.cenqua.com/browse/hudson/hudson/main/core/src/main/java/hudson/tasks/junit/CaseResult.java