diff --git a/.gitignore b/.gitignore index 1df48b45b..c0e2f997d 100644 --- a/.gitignore +++ b/.gitignore @@ -55,3 +55,8 @@ src/ScriptEngine.Snegopat/Snegopat_h.h # Песональный вспомагательный скрипт build.user.bat src/packages/ + +# Visual Studio OpenCover and Test result +src/OpenCover +TestResult.xml +tests/component/Component.dll diff --git a/BuildAll.csproj b/BuildAll.csproj index 30bacbbfb..1df64f235 100644 --- a/BuildAll.csproj +++ b/BuildAll.csproj @@ -1,169 +1,190 @@ - - - Release - $(MSBuildProjectDirectory)\install\build\ - $(MSBuildProjectDirectory)\dist\ + + + Release + $(MSBuildProjectDirectory)\install\build\ + $(MSBuildProjectDirectory)\dist\ $(OutputPathForBuild)\bin\ $(OutputPathForBuild)\lib\ $(OutputPathForBuild)\doc\ - $(MSBuildProjectDirectory)\mddoc\ + $(MSBuildProjectDirectory)\mddoc $(OutputPathForBuild)\examples\ - $(MSBuildProjectDirectory)\src\1Script.sln - "$(InnoSetupPath)\iscc.exe" + $(MSBuildProjectDirectory)\src\1Script.sln + "$(InnoSetupPath)\iscc.exe" "$(NugetPath)\nuget.exe" - 1 - 0 - 11 - 0 - - + 1 + 0 + 11 + 0 + + - - - $(ReleaseNumber) + + + $(ReleaseNumber) $(Build)$(Suffix) - - - - - $(BUILD_NUMBER) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - + + + $(BUILD_NUMBER) + + - - - - - - - - - - - - - - - + + + + + + + - - - "$(CertPassword)" - "$(CertPath)" - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + "$(CertPassword)" + "$(CertPath)" + + + + + + + + - - - - - - - - - + + + + + + + + @@ -173,39 +194,36 @@ - - - + + + - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 000000000..5f33755c2 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,133 @@ + +pipeline { + + agent none + + environment { + ReleaseNumber = 17 + outputEnc = '65001' + } + + stages { + stage('Windows Build') { + agent { label 'windows' } + + // пути к инструментам доступны только когда + // нода уже определена + environment { + NugetPath = "${tool 'nuget'}" + OneScriptDocumenter = "${tool 'documenter'}" + } + + steps { + + // в среде Multibranch Pipeline Jenkins первращает имена веток в папки + // а для веток Gitflow вида release/* экранирует в слэш в %2F + // При этом MSBuild, видя urlEncoding, разэкранирует его обратно, ломая путь (появляется слэш, где не надо) + // + // Поэтому, применяем костыль с кастомным workspace + // см. https://issues.jenkins-ci.org/browse/JENKINS-34564 + + ws("$workspace".replaceAll("%", "_")) + { + checkout scm + + bat 'set' + bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" BuildAll.csproj /p:Configuration=Release /p:Platform=x86 /t:Build" + + stash includes: 'tests, install/build/**, mddoc/**', name: 'buildResults' + } + } + + } + + stage('Windows testing') { + agent { label 'windows' } + + steps { + ws("$workspace".replaceAll("%", "_")) + { + unstash 'buildResults' + bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" BuildAll.csproj /p:Configuration=Release /p:Platform=x86 /t:xUnitTest" + + junit 'tests/tests.xml' + } + } + } + + stage('Linux testing') { + + agent { label 'master' } + + steps { + unstash 'buildResults' + + sh '''\ + if [ ! -d lintests ]; then + mkdir lintests + fi + + rm lintests/*.xml -f + cd tests + mono ../install/build/bin/oscript.exe testrunner.os -runall . xddReportPath ../lintests || true + exit 0 + '''.stripIndent() + + junit 'lintests/*.xml' + archiveArtifacts artifacts: 'lintests/*.xml', fingerprint: true + } + + + + } + + stage('Packaging') { + agent { label 'windows' } + + environment { + NugetPath = "${tool 'nuget'}" + InnoSetupPath = "${tool 'InnoSetup'}" + } + + steps { + ws("$workspace".replaceAll("%", "_")) + { + unstash 'buildResults' + //unstash 'sitedoc' + bat "chcp $outputEnc > nul\r\n\"${tool 'MSBuild'}\" BuildAll.csproj /p:Configuration=Release /p:Platform=x86 /t:CreateZip;CreateInstall;CreateNuget" + archiveArtifacts artifacts: '**/dist/*.exe, **/dist/*.msi, **/dist/*.zip, **/dist/*.nupkg, **/tests/*.xml', fingerprint: true + } + } + } + + stage ('Packaging DEB and RPM') { + agent { label 'master' } + + steps { + + checkout scm + unstash 'buildResults' + + sh ''' + cd install + chmod +x prepare-build.sh + chmod +x deb-build.sh + chmod +x rpm-build.sh + + sh ./prepare-build.sh + + DISTPATH=`pwd`/build + + sh ./deb-build.sh $DISTPATH + sh ./rpm-build.sh $DISTPATH + '''.stripIndent() + + archiveArtifacts artifacts: 'output/*', fingerprint: true + + } + + } + + } + +} \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index d3e01f386..56e68582f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: 1.0.16-alpha{build} +version: 1.0.17-alpha{build} pull_requests: do_not_increment_build_number: true configuration: Release diff --git a/codecov.io.sh b/codecov.io.sh new file mode 100644 index 000000000..bd8dd3075 --- /dev/null +++ b/codecov.io.sh @@ -0,0 +1,4 @@ +echo "dont forget pip install codecov" +echo "and dont forget set CODECOV_TOKEN" + +codecov -f $(pwd)/src/OpenCover/opencover.xml diff --git a/cover.bat b/cover.bat new file mode 100644 index 000000000..3bc6b927b --- /dev/null +++ b/cover.bat @@ -0,0 +1,7 @@ +echo "Run testrunner.os behind NUnit with OpenCover" +echo "generate OpneCover.xml to external services like Coverals.io" +echo "Create local report for contributor ;-)" + +"%CD%\src\packages\OpenCover.4.6.519\tools\OpenCover.Console.exe" -output:"%CD%\src\OpenCover\opencover.xml" -target:./src/packages/NUnit.ConsoleRunner.3.5.0/tools/nunit3-console.exe -targetargs:"./src/NUnitTests/bin/Release/NUnitTests.dll" -register:user + +"%CD%\src\packages\ReportGenerator.2.5.1\tools\ReportGenerator.exe" -reports:"%CD%\src\OpenCover\opencover.xml" -targetdir:"%CD%\src\OpenCover\CodeCovLocal" diff --git a/coverals.io.bat b/coverals.io.bat new file mode 100644 index 000000000..1bac2029a --- /dev/null +++ b/coverals.io.bat @@ -0,0 +1,5 @@ +echo "Publish coverals io info" +echo "dont forget set secure repo token ;-) COVERALLS_REPO_TOKEN" +echo "dont forget use branch and pull request params" + +"%CD%\src\packages\coveralls.net.0.7.0\tools\csmacnz.Coveralls.exe" --useRelativePaths --opencover -i %CD%\src\OpenCover\opencover.xml diff --git a/install/build.sh b/install/build.sh index 89139184a..774a779db 100755 --- a/install/build.sh +++ b/install/build.sh @@ -4,5 +4,5 @@ # ./build.sh /p:Platform="x86" to build for x86 cd `dirname $0` -xbuild /p:Platform="Any CPU" /p:Configuration="Release" $@ ../src/1Script_Mono.sln +msbuild /p:Platform="Any CPU" /p:Configuration="Release" $@ ../src/1Script_Mono.sln diff --git a/install/builders/deb/Dockerfile b/install/builders/deb/Dockerfile index ef4fc13f1..250cffb20 100644 --- a/install/builders/deb/Dockerfile +++ b/install/builders/deb/Dockerfile @@ -1,31 +1,33 @@ -FROM ubuntu:latest +FROM ubuntu:16.04 MAINTAINER sergey.batanov@dmpas.ru -# чтобы запустить тесты -RUN locale-gen --lang ru_RU.UTF-8 -ENV LANG ru_RU.UTF-8 - # Add mono repository -RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF && \ - echo "deb http://download.mono-project.com/repo/debian wheezy main" > /etc/apt/sources.list.d/mono-xamarin.list +#RUN apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 3FA7E0328081BFF6A14DA29AA6A19B38D3D831EF && \ +# echo "deb http://download.mono-project.com/repo/debian wheezy main" > /etc/apt/sources.list.d/mono-xamarin.list RUN apt-get update && apt-get install -y \ # runtime dependencies - mono-runtime \ - libmono-system-core4.0-cil \ - libmono-system4.0-cil \ - libmono-corlib4.0-cil \ - libmono-i18n4.0-all \ +# mono-runtime \ +# libmono-system-core4.0-cil \ +# libmono-system4.0-cil \ +# libmono-corlib4.0-cil \ +# libmono-i18n4.0-all \ # deb-package tools dpkg\ debconf\ debhelper\ lintian\ md5deep\ - fakeroot + fakeroot \ + locales + +# чтобы запустить тесты +RUN locale-gen --lang ru_RU.UTF-8 +ENV LANG ru_RU.UTF-8 + +COPY ./ /opt/deb/ -ADD ./build.sh /root/ -ENTRYPOINT /root/build.sh +ENTRYPOINT /opt/deb/build.sh diff --git a/install/builders/deb/build.sh b/install/builders/deb/build.sh index 197b5cf3e..7779c547f 100755 --- a/install/builders/deb/build.sh +++ b/install/builders/deb/build.sh @@ -1,11 +1,17 @@ #!/bin/sh -SRCPATH=/media +DATAROOT=/media +SRCPATH=${DATAROOT}/src BINPATH=${SRCPATH}/bin/ -DEBBUILDROOT=${SRCPATH}/bin/ -BUILDERROOT=${SRCPATH}/deb/ +DEBBUILDROOT=${DATAROOT}/deb/ +BUILDERROOT=/opt/deb/ -VERSION=$(cat ${BINPATH}VERSION) +if [ -d "$DEBBUILDROOT" ]; then + rm -rf $DEBBUILDROOT + mkdir $DEBBUILDROOT +fi + +VERSION=$(cat ${DATAROOT}/VERSION) PAKNAME=onescript-engine DSTPATH=${DEBBUILDROOT}${PAKNAME} diff --git a/install/builders/rpm/Dockerfile b/install/builders/rpm/Dockerfile index 50d3592ed..219730a68 100644 --- a/install/builders/rpm/Dockerfile +++ b/install/builders/rpm/Dockerfile @@ -13,6 +13,8 @@ RUN sed -i.bak -n -e '/^Defaults.*requiretty/ { s/^/# /;};/^%wheel.*ALL$/ { s/^/ # This is an optimisation for caching, since using the auto generated one will # make docker always run the builddep steps since new file ADD oscript.spec /tmp/ +ADD oscript /tmp/ + RUN dnf builddep -y --spec /tmp/oscript.spec ADD start.sh /start.sh diff --git a/install/builders/rpm/oscript b/install/builders/rpm/oscript new file mode 100644 index 000000000..65af38659 --- /dev/null +++ b/install/builders/rpm/oscript @@ -0,0 +1,3 @@ +#!/bin/sh +mono /usr/share/oscript/bin/oscript.exe "$@" + diff --git a/install/builders/rpm/start.sh b/install/builders/rpm/start.sh index bd8879792..08c89eed6 100755 --- a/install/builders/rpm/start.sh +++ b/install/builders/rpm/start.sh @@ -1,5 +1,32 @@ #!/bin/bash # script run inside the container + + +#/media/src/bin;lib;examples;etc +#/media/VERSIONFILE +VERSIONFILE=/media/VERSION +DISTPATH=/media/src + +VERSION=$(cat ${VERSIONFILE}) +BLDTMP=/tmp +TMPDIR=${BLDTMP}/OneScript-$VERSION +mkdir -p $TMPDIR + +echo "Copying sources to tmpdir" +cp -r -v $DISTPATH/* $TMPDIR +cp -r -v ${BLDTMP}/oscript $TMPDIR/oscript + +pushd ${BLDTMP} +echo "Compressing OneScript-$VERSION to tar" +tar -czvf OneScript-$VERSION.tar.gz OneScript-$VERSION/ +popd + +BUILDDIR=/media/rpm +sudo mkdir -p ${BUILDDIR} + +#cp -ra $BLDTMP/OneScript-$VERSION.tar.gz $BUILDDIR/ +#cp -rf $BLDTMP/oscript.spec $BUILDDIR/ + rpmdev-setuptree define="" if [ -z $VERSION ]; then @@ -15,16 +42,16 @@ else fi echo $define -sudo cp -arv /media/* rpmbuild/SOURCES/ -sudo cp -arv /media/*.spec rpmbuild/SPECS/ +sudo cp -arv $BLDTMP/* rpmbuild/SOURCES/ +sudo cp -arv $BLDTMP/*.spec rpmbuild/SPECS/ rpmbuild -ba \ --define "_version ${VERSION:-1.0.13}" \ rpmbuild/SPECS/oscript.spec || exit 1 -[[ -d /media ]] || exit 0 +[[ -d $BUILDDIR ]] || exit 0 -sudo mkdir -p /media/RPMS -sudo mkdir -p /media/SRPMS +sudo mkdir -p $BUILDDIR/RPMS +sudo mkdir -p $BUILDDIR/SRPMS -sudo cp -ar rpmbuild/RPMS/ /media/ -sudo cp -ar rpmbuild/SRPMS/ /media/ +sudo cp -ar rpmbuild/RPMS/ $BUILDDIR/ +sudo cp -ar rpmbuild/SRPMS/ $BUILDDIR/ diff --git a/install/deb-build.sh b/install/deb-build.sh index 5e5c6590e..3ccee8ffc 100755 --- a/install/deb-build.sh +++ b/install/deb-build.sh @@ -1,28 +1,17 @@ #!/bin/bash DISTPATH=$(cd $1; pwd) -BINPATH=$DISTPATH/bin cd `dirname $0` echo "Assets folder: $DISTPATH" echo "Current dir: {$PWD}" -VERSIONFILE=$BINPATH/VERSION -if [ -f "$VERSIONFILE" ] ; then - rm $VERSIONFILE -fi - -mono ${BINPATH}/oscript.exe -version | \ - grep -oE '([[:digit:]]+\.){2}[[:digit:]]+' \ - > ${BINPATH}/VERSION +docker build -t onescript:deb ${PWD}/builders/deb/ +docker run --rm -v os_bld_output:/media onescript:deb -if [ ! -f "$VERSIONFILE" ] ; then - echo "No version file created" - exit 1 -fi - -mkdir -p $DISTPATH/deb -cp -r ${PWD}/builders/deb/* $DISTPATH/deb +TMPOUT=../output +rm -rf $TMPOUT/deb -docker build -t onescript:deb ${PWD}/builders/deb/ -docker run --rm -v ${DISTPATH}:/media onescript:deb +docker cp bldxchg:/bld/deb/ $TMPOUT +mv $TMPOUT/deb/*.deb $TMPOUT +rm -rf $TMPOUT/deb diff --git a/install/prepare-build.sh b/install/prepare-build.sh new file mode 100644 index 000000000..48ab9758d --- /dev/null +++ b/install/prepare-build.sh @@ -0,0 +1,41 @@ +#!/bin/bash + +echo 'Preparing environment' + +DISTPATH=$(pwd)/build +BINPATH=${DISTPATH}/bin +cd `dirname $0` + +docker volume create os_bld_output + +if [ "$(docker ps -aq -f name=bldxchg)" ]; then + echo 'Exchange exist. Run it' + docker start bldxchg +else + echo 'Creating Exchange' + docker run --name bldxchg -v os_bld_output:/bld busybox rm -rf /bld/ +fi + +VERSIONFILE=$DISTPATH/VERSION +if [ -f "$VERSIONFILE" ] ; then + rm $VERSIONFILE +fi + +mono ${BINPATH}/oscript.exe -version | \ + grep -oE '([[:digit:]]+\.){2}[[:digit:]]+' \ + > ${VERSIONFILE} + +if [ ! -f "$VERSIONFILE" ] ; then + echo "No version file created" + exit 1 +fi + +docker cp $VERSIONFILE bldxchg:/bld +rm $VERSIONFILE +docker cp build/ bldxchg:/bld/src/ + +OUTPUT="../output" +if [ -d "$OUTPUT" ]; then + rm -rf ${OUTPUT} +fi +mkdir ${OUTPUT} diff --git a/install/rpm-build.sh b/install/rpm-build.sh index 70f019e3f..83dad9f8c 100755 --- a/install/rpm-build.sh +++ b/install/rpm-build.sh @@ -1,6 +1,8 @@ #!/bin/bash #set -exf +echo "Building RPM" + PROJECT=oscript echo "$0" echo "$1" @@ -10,39 +12,18 @@ cd `dirname $0` echo "Assets folder: $DISTPATH" echo "Current dir: {$PWD}" - -if [ -z "$TMP" ] ; then - TMP=/tmp -fi - -VERSION=`mono ${BINPATH}/oscript.exe -version | \ - grep -oE '([[:digit:]]+\.){2}[[:digit:]]+'` - -echo "Version is $VERSION" - -TMPDIR=$TMP/OneScript-$VERSION -mkdir $TMPDIR -echo "Created TMPDIR $TMPDIR" - -echo "Copying sources to tmpdir" -cp -r -v $DISTPATH/* $TMPDIR -cp -r -v ../install/builders/deb/oscript $TMPDIR/oscript - -pushd $TMP -echo "Compressing OneScript-$VERSION to tar" -tar -czvf OneScript-$VERSION.tar.gz OneScript-$VERSION/ -popd - -mkdir -p $TMP/$PROJECT-$VERSION-build -BUILDDIR=$TMP/$PROJECT-$VERSION-build -echo "Created build dir: $BUILDDIR" - -cp -ra $TMP/OneScript-$VERSION.tar.gz $BUILDDIR/ -cp -rf ./builders/rpm/oscript.spec $BUILDDIR/ docker build -t onescript:rpm ${PWD}/builders/rpm/ -docker run --rm -e VERSION=$VERSION -v ${BUILDDIR}:/media onescript:rpm +docker run --rm -v os_bld_output:/media onescript:rpm + +TMPOUT=../output +rm -rf $TMPOUT/rpm + +docker cp bldxchg:/bld/rpm/ $TMPOUT +if [ $? -ne 0 ]; then + exit 1 +fi -cp $BUILDDIR/RPMS/noarch/*.rpm $BINPATH/ -cp $BUILDDIR/SRPMS/*.rpm $BINPATH/ -rm -rd $BUILDDIR +mv $TMPOUT/rpm/RPMS/noarch/*.rpm $TMPOUT +mv $TMPOUT/rpm/SRPMS/*.rpm $TMPOUT +rm -rf $TMPOUT/rpm \ No newline at end of file diff --git a/install/unicode-zipper.os b/install/unicode-zipper.os index 597457aef..a64faa611 100644 --- a/install/unicode-zipper.os +++ b/install/unicode-zipper.os @@ -23,7 +23,7 @@ КонецПроцедуры -Процедура Выполнить() +Процедура ВыполнитьОбработку() Команда = АргументыКоманднойСтроки[0]; Если Команда = "pack" Тогда @@ -39,7 +39,7 @@ //////////////////////////////////////////////////////////////////// Попытка - Выполнить(); + ВыполнитьОбработку(); Исключение Сообщить(ОписаниеОшибки()); ЗавершитьРаботу(1); diff --git a/oscript-library b/oscript-library index d161c1d91..7b0c542a6 160000 --- a/oscript-library +++ b/oscript-library @@ -1 +1 @@ -Subproject commit d161c1d9152f8009b6850bee798e746fba6d5805 +Subproject commit 7b0c542a65da429eed263d1b516a7e92e1780fed diff --git a/src/1Script.sln b/src/1Script.sln index 38a9dbac9..63adfb482 100644 --- a/src/1Script.sln +++ b/src/1Script.sln @@ -26,34 +26,83 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution EndProject Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Installer", "Installer\Installer.wixproj", "{BBE794A6-B159-422F-B655-B7F03F25F223}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUnitTests", "NUnitTests\NUnitTests.csproj", "{93ACC849-E7E1-4695-B59D-54B3737E48A6}" + ProjectSection(ProjectDependencies) = postProject + {2590E2BB-CC1F-4775-80ED-451F45C9A4F1} = {2590E2BB-CC1F-4775-80ED-451F45C9A4F1} + {F09A46BD-5737-45E7-BA60-A47C9F7821A9} = {F09A46BD-5737-45E7-BA60-A47C9F7821A9} + {F062D1D9-D307-492A-A56B-FF3C55F8F6C0} = {F062D1D9-D307-492A-A56B-FF3C55F8F6C0} + {795AA2F5-3074-4BC5-A30F-1B6354044D9B} = {795AA2F5-3074-4BC5-A30F-1B6354044D9B} + EndProjectSection +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Component", "Component\Component.csproj", "{B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU Debug|x86 = Debug|x86 + Release|Any CPU = Release|Any CPU Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {4585BA5D-9EC4-4C89-8250-2033D2AC2999}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4585BA5D-9EC4-4C89-8250-2033D2AC2999}.Debug|Any CPU.Build.0 = Debug|Any CPU {4585BA5D-9EC4-4C89-8250-2033D2AC2999}.Debug|x86.ActiveCfg = Debug|x86 {4585BA5D-9EC4-4C89-8250-2033D2AC2999}.Debug|x86.Build.0 = Debug|x86 + {4585BA5D-9EC4-4C89-8250-2033D2AC2999}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4585BA5D-9EC4-4C89-8250-2033D2AC2999}.Release|Any CPU.Build.0 = Release|Any CPU {4585BA5D-9EC4-4C89-8250-2033D2AC2999}.Release|x86.ActiveCfg = Release|x86 {4585BA5D-9EC4-4C89-8250-2033D2AC2999}.Release|x86.Build.0 = Release|x86 + {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Debug|Any CPU.Build.0 = Debug|Any CPU {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Debug|x86.ActiveCfg = Debug|Any CPU {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Debug|x86.Build.0 = Debug|Any CPU + {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Release|Any CPU.Build.0 = Release|Any CPU {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Release|x86.ActiveCfg = Release|Any CPU {F062D1D9-D307-492A-A56B-FF3C55F8F6C0}.Release|x86.Build.0 = Release|Any CPU + {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Debug|Any CPU.Build.0 = Debug|Any CPU {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Debug|x86.ActiveCfg = Debug|Any CPU {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Debug|x86.Build.0 = Debug|Any CPU + {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Release|Any CPU.Build.0 = Release|Any CPU {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Release|x86.ActiveCfg = Release|Any CPU {F09A46BD-5737-45E7-BA60-A47C9F7821A9}.Release|x86.Build.0 = Release|Any CPU + {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Debug|Any CPU.Build.0 = Debug|Any CPU {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Debug|x86.ActiveCfg = Debug|x86 {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Debug|x86.Build.0 = Debug|x86 + {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Release|Any CPU.Build.0 = Release|Any CPU {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Release|x86.ActiveCfg = Release|x86 {2590E2BB-CC1F-4775-80ED-451F45C9A4F1}.Release|x86.Build.0 = Release|x86 + {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Debug|Any CPU.Build.0 = Debug|Any CPU {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Debug|x86.ActiveCfg = Debug|x86 {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Debug|x86.Build.0 = Debug|x86 + {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Release|Any CPU.Build.0 = Release|Any CPU {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Release|x86.ActiveCfg = Release|x86 {795AA2F5-3074-4BC5-A30F-1B6354044D9B}.Release|x86.Build.0 = Release|x86 + {BBE794A6-B159-422F-B655-B7F03F25F223}.Debug|Any CPU.ActiveCfg = Debug|x86 {BBE794A6-B159-422F-B655-B7F03F25F223}.Debug|x86.ActiveCfg = Debug|x86 + {BBE794A6-B159-422F-B655-B7F03F25F223}.Release|Any CPU.ActiveCfg = Release|x86 {BBE794A6-B159-422F-B655-B7F03F25F223}.Release|x86.ActiveCfg = Release|x86 + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|x86.ActiveCfg = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|x86.Build.0 = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Any CPU.Build.0 = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|x86.ActiveCfg = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|x86.Build.0 = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|x86.ActiveCfg = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|x86.Build.0 = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Any CPU.Build.0 = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|x86.ActiveCfg = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/1Script_Mono.sln b/src/1Script_Mono.sln index 9295a3ae9..51ed2becf 100644 --- a/src/1Script_Mono.sln +++ b/src/1Script_Mono.sln @@ -12,6 +12,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "oscript", "oscript\oscript. EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandaloneRunner", "StandaloneRunner\StandaloneRunner.csproj", "{795AA2F5-3074-4BC5-A30F-1B6354044D9B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NUnitTests", "NUnitTests\NUnitTests.csproj", "{93ACC849-E7E1-4695-B59D-54B3737E48A6}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Component", "Component\Component.csproj", "{B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -103,6 +107,38 @@ Global {618F7216-6576-410D-818C-C79BB6BEEA0C}.Release|Win32.Build.0 = Release|Win32 {618F7216-6576-410D-818C-C79BB6BEEA0C}.Release|x86.ActiveCfg = Release|Win32 {618F7216-6576-410D-818C-C79BB6BEEA0C}.Release|x86.Build.0 = Release|Win32 + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Win32.ActiveCfg = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|Win32.Build.0 = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|x86.ActiveCfg = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Debug|x86.Build.0 = Debug|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Any CPU.Build.0 = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Win32.ActiveCfg = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|Win32.Build.0 = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|x86.ActiveCfg = Release|Any CPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6}.Release|x86.Build.0 = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Win32.ActiveCfg = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|Win32.Build.0 = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|x86.ActiveCfg = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Debug|x86.Build.0 = Debug|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Any CPU.Build.0 = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Win32.ActiveCfg = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|Win32.Build.0 = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|x86.ActiveCfg = Release|Any CPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution Policies = $0 @@ -111,7 +147,7 @@ Global $1.ResourceNamePolicy = FileFormatDefault $0.TextStylePolicy = $2 $2.inheritsSet = null - $2.scope = application/xml + $2.scope = text/x-csharp $2.FileWidth = 120 $2.inheritsScope = text/plain $2.TabsToSpaces = False diff --git a/src/Component/Component.csproj b/src/Component/Component.csproj new file mode 100644 index 000000000..0ee74813d --- /dev/null +++ b/src/Component/Component.csproj @@ -0,0 +1,64 @@ + + + + Debug + AnyCPU + {B6C3C000-699B-4A2F-92D1-EEAEA9CFE2AB} + Library + Component + Component + v4.5 + + + true + full + false + bin\Debug + DEBUG; + prompt + 4 + false + + + true + bin\Release + prompt + 4 + false + + + + + + + + + + + + + + + {F062D1D9-D307-492A-A56B-FF3C55F8F6C0} + ScriptEngine + + + {F09A46BD-5737-45E7-BA60-A47C9F7821A9} + ScriptEngine.HostedScript + + + + + + + + + + + + + + xcopy "$(TargetDir)Component.dll" "$(SolutionDir)..\tests\component" /Y /E /D + cp -f "$(TargetDir)Component.dll" "$(SolutionDir)../tests/component" + + diff --git a/src/Component/ISimple.cs b/src/Component/ISimple.cs new file mode 100644 index 000000000..6ca603e06 --- /dev/null +++ b/src/Component/ISimple.cs @@ -0,0 +1,13 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; +namespace Component +{ + public interface ISimple + { + } +} diff --git a/src/Component/Properties/AssemblyInfo.cs b/src/Component/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..4bee8397e --- /dev/null +++ b/src/Component/Properties/AssemblyInfo.cs @@ -0,0 +1,32 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System.Reflection; +using System.Runtime.CompilerServices; + +// Information about this assembly is defined by the following attributes. +// Change them to the values specific to your project. + +[assembly: AssemblyTitle("Component")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("")] +[assembly: AssemblyCopyright("${AuthorCopyright}")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}". +// The form "{Major}.{Minor}.*" will automatically update the build and revision, +// and "{Major}.{Minor}.{Build}.*" will update just the revision. + +[assembly: AssemblyVersion("1.0.*")] + +// The following attributes are used to specify the signing key for the assembly, +// if desired. See the Mono documentation for more information about signing. + +//[assembly: AssemblyDelaySign(false)] +//[assembly: AssemblyKeyFile("")] diff --git a/src/Component/SimpleClass.cs b/src/Component/SimpleClass.cs new file mode 100644 index 000000000..b9d3cedb0 --- /dev/null +++ b/src/Component/SimpleClass.cs @@ -0,0 +1,44 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; +using ScriptEngine.Machine.Contexts; +using ScriptEngine.Machine; + +namespace Component +{ + [ContextClass("ПростоКласс")] + public sealed class SimpleClass : AutoContext, ISimple + { + public SimpleClass() + { + } + + [ContextProperty("СвойствоПеречисление")] + public SimpleEnum EnumProperty { get; set; } + + [ContextProperty("ЦелочисленноеСвойство")] + public int IntProperty { get; set; } + + [ContextProperty("СвойствоСПроизвольнымЗначением")] + public IValue AnyValueProperty { get; set; } + + + [ScriptConstructor] + public static IRuntimeContextInstance Constructor() + { + return new SimpleClass(); + } + + [ScriptConstructor] + public static IRuntimeContextInstance Constructor(IValue initialProperty) + { + var result = new SimpleClass(); + result.IntProperty = ContextValuesMarshaller.ConvertParam(initialProperty); + return result; + } + } +} diff --git a/src/Component/SimpleCollection.cs b/src/Component/SimpleCollection.cs new file mode 100644 index 000000000..a922bb624 --- /dev/null +++ b/src/Component/SimpleCollection.cs @@ -0,0 +1,58 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; +using ScriptEngine.Machine.Contexts; +using System.Collections.Generic; +using ScriptEngine.Machine; +using System.Collections; + +namespace Component +{ + [ContextClass("ПростоКоллекция")] + public sealed class SimpleCollection : AutoContext, ICollectionContext, IEnumerable + { + + readonly List _data = new List(); + + public SimpleCollection() + { + } + + [ContextMethod("Добавить")] + public void Add(SimpleClass item) + { + _data.Add(item); + } + + [ContextMethod("Количество")] + public int Count() + { + return _data.Count; + } + + public IEnumerator GetEnumerator() + { + return ((IEnumerable)_data).GetEnumerator(); + } + + public CollectionEnumerator GetManagedIterator() + { + return new CollectionEnumerator(GetEnumerator()); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_data).GetEnumerator(); + } + + [ScriptConstructor] + public static IRuntimeContextInstance Constructor() + { + return new SimpleCollection(); + } + } +} diff --git a/src/Component/SimpleEnum.cs b/src/Component/SimpleEnum.cs new file mode 100644 index 000000000..75be5036f --- /dev/null +++ b/src/Component/SimpleEnum.cs @@ -0,0 +1,21 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; +using ScriptEngine; + +namespace Component +{ + [EnumerationType("ПростоПеречисление")] + public enum SimpleEnum + { + [EnumItem("Элемент1")] + Item1, + + [EnumItem("Элемент2")] + Item2 + } +} diff --git a/src/Component/UseLibrary.cs b/src/Component/UseLibrary.cs new file mode 100644 index 000000000..705881be4 --- /dev/null +++ b/src/Component/UseLibrary.cs @@ -0,0 +1,90 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine; + + +namespace Component +{ + public static class UseLibrary + { + + public static void Use() where T : IValue + { + + } + + public static void Use() + { + /* Суть следующих выражений в том, что они перестанут компилироваться, + если какой-либо из классов поменяет область видимости + или переедет в иное пространство имён + (https://github.com/EvilBeaver/OneScript/commit/20e48fa7692b5430b819eb4b6982be1b591e536f)*/ + + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + + Use(); + Use(); + Use(); + Use(); + + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + Use(); + + Use(); + Use(); + Use(); + Use(); + + Use(); + Use(); + + Use(); + Use(); + Use(); + Use(); + + Use(); + Use(); + + Use(); + Use(); + Use(); + Use(); + Use(); + + Use(); + Use(); + Use(); + Use(); + + Use(); + Use(); + Use(); + + Use(); + Use(); + + } + } +} diff --git a/src/GlobalAssemblyInfo.cs b/src/GlobalAssemblyInfo.cs index 2f65028f5..0130fb7a9 100644 --- a/src/GlobalAssemblyInfo.cs +++ b/src/GlobalAssemblyInfo.cs @@ -15,11 +15,11 @@ This Source Code Form is subject to the terms of the //------------------------------------------------------------------------------ [assembly: System.Reflection.AssemblyCompany("BeaverSoft")] -[assembly: System.Reflection.AssemblyCopyright("Copyright (c) 2016 EvilBeaver")] +[assembly: System.Reflection.AssemblyCopyright("Copyright (c) 2017 EvilBeaver")] [assembly: System.Reflection.AssemblyConfiguration("Commit 2a614c0")] -[assembly: System.Reflection.AssemblyVersion("1.0.16.0")] -[assembly: System.Reflection.AssemblyFileVersion("1.0.16.0")] -[assembly: System.Reflection.AssemblyInformationalVersion("1.0.16.0")] +[assembly: System.Reflection.AssemblyVersion("1.0.17.0")] +[assembly: System.Reflection.AssemblyFileVersion("1.0.17.0")] +[assembly: System.Reflection.AssemblyInformationalVersion("1.0.17.0")] @@ -27,15 +27,15 @@ internal sealed partial class ThisAssembly { internal const string AssemblyCompany = "BeaverSoft"; - internal const string AssemblyCopyright = "Copyright (c) 2016 EvilBeaver"; + internal const string AssemblyCopyright = "Copyright (c) 2017 EvilBeaver"; internal const string AssemblyConfiguration = "Commit 2a614c0"; - internal const string AssemblyVersion = "1.0.14.0"; + internal const string AssemblyVersion = "1.0.17.0"; - internal const string AssemblyFileVersion = "1.0.14.0"; + internal const string AssemblyFileVersion = "1.0.17.0"; - internal const string AssemblyInformationalVersion = "1.0.14.0"; + internal const string AssemblyInformationalVersion = "1.0.17.0"; private ThisAssembly() { } diff --git a/src/NUnitTests/EngineWrapperNUnit.cs b/src/NUnitTests/EngineWrapperNUnit.cs new file mode 100644 index 000000000..f7d1c584b --- /dev/null +++ b/src/NUnitTests/EngineWrapperNUnit.cs @@ -0,0 +1,98 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using ScriptEngine.Machine.Contexts; +using ScriptEngine.HostedScript.Library; +using ScriptEngine.Machine; +using ScriptEngine.Environment; +using ScriptEngine.HostedScript; +using System.IO; + +namespace NUnitTests +{ + class EngineWrapperNUnit : IHostApplication + { + + private HostedScriptEngine engine; + private string[] commandLineArgs; + + public HostedScriptEngine StartEngine() + { + engine = new HostedScriptEngine(); + engine.Initialize(); + + commandLineArgs = new string[] { }; + + return engine; + } + + private int RunTestScript(ICodeSource source, string resourceName) + { + var module = engine.GetCompilerService().CreateModule(source); + + engine.LoadUserScript(new ScriptEngine.UserAddedScript() + { + Type = ScriptEngine.UserAddedScriptType.Class, + Module = module, + Symbol = resourceName + }); + + var process = engine.CreateProcess(this, source); + return process.Start(); + } + + internal int RunTestScriptFromPath(string scriptFilePath, String argsScript = "") + { + if (argsScript != "") + { + commandLineArgs = argsScript.Split(' '); + } + + ICodeSource sourceToCompile = engine.Loader.FromFile(scriptFilePath); + + return RunTestScript(sourceToCompile, scriptFilePath); + } + + public EngineWrapperNUnit() + { + } + public string[] GetCommandLineArguments() + { + return this.commandLineArgs; + } + + public bool InputString(out string result, int maxLen) + { + result = ""; + return false; + } + + public void ShowExceptionInfo(Exception exc) + { + throw exc; + } + + public void Echo(string str, MessageStatusEnum status = MessageStatusEnum.Ordinary) + { + Console.WriteLine(str); + } + + public HostedScriptEngine Engine + { + get + { + return engine; + } + } + + } +} diff --git a/src/NUnitTests/NUnitTests.csproj b/src/NUnitTests/NUnitTests.csproj new file mode 100644 index 000000000..01674d709 --- /dev/null +++ b/src/NUnitTests/NUnitTests.csproj @@ -0,0 +1,104 @@ + + + + Debug + AnyCPU + {93ACC849-E7E1-4695-B59D-54B3737E48A6} + Library + Properties + NUnitTests + NUnitTests + v4.5.2 + 512 + {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll + True + + + + + + + + + + + + + + + + + + + + + + + {f09a46bd-5737-45e7-ba60-a47c9f7821a9} + ScriptEngine.HostedScript + + + {f062d1d9-d307-492a-a56b-ff3c55f8f6c0} + ScriptEngine + + + + + + + + + + + + + False + + + False + + + False + + + False + + + + + + + + \ No newline at end of file diff --git a/src/NUnitTests/Properties/AssemblyInfo.cs b/src/NUnitTests/Properties/AssemblyInfo.cs new file mode 100644 index 000000000..48b5d8499 --- /dev/null +++ b/src/NUnitTests/Properties/AssemblyInfo.cs @@ -0,0 +1,42 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// Управление общими сведениями о сборке осуществляется посредством следующего +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("NUnitTests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("NUnitTests")] +[assembly: AssemblyCopyright("Copyright © 2016")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Задание значения false для атрибута ComVisible приведет к тому, что типы из этой сборки станут невидимыми +// для COM-компонентов. Если к одному из типов этой сборки необходимо обращаться из +// модели COM, задайте для атрибута ComVisible этого типа значение true. +[assembly: ComVisible(false)] + +// Если данный проект доступен для модели COM, следующий GUID используется в качестве идентификатора библиотеки типов +[assembly: Guid("93acc849-e7e1-4695-b59d-54b3737e48a6")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Редакция +// +// Можно задать все значения или принять номера сборки и редакции по умолчанию +// используя "*", как показано ниже: +// [сборка: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/src/NUnitTests/TestRunnerTest.cs b/src/NUnitTests/TestRunnerTest.cs new file mode 100644 index 000000000..61d208099 --- /dev/null +++ b/src/NUnitTests/TestRunnerTest.cs @@ -0,0 +1,46 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; +using System.IO; +using NUnit.Framework; + +namespace NUnitTests +{ + [TestFixture] + public class UnitTestWrapper + { + const int TEST_STATE_FAILED = 3; + + private EngineWrapperNUnit host; + private string solutionRoot; + + [OneTimeSetUp] + public void Initialize() + { + host = new EngineWrapperNUnit(); + host.StartEngine(); + solutionRoot = Path.Combine(TestContext.CurrentContext.TestDirectory, "..", "..", "..", ".."); + host.Engine.InitExternalLibraries(Path.Combine(solutionRoot, "oscript-library", "src"), null); + } + + [Test] + public void RunEngineTests() + { + String testRunnerPath = Path.Combine(solutionRoot, "tests", "testrunner.os"); + + Assert.IsTrue(File.Exists(testRunnerPath), + "Запускатель тестов отсутствует по пути " + testRunnerPath); + + var result = host.RunTestScriptFromPath(testRunnerPath, "-runall " + new System.IO.FileInfo(testRunnerPath).Directory.FullName); + + if (result == TEST_STATE_FAILED) + { + NUnit.Framework.Assert.Fail("Есть непройденные тесты!"); + } + } + } +} diff --git a/src/NUnitTests/packages.config b/src/NUnitTests/packages.config new file mode 100644 index 000000000..309342441 --- /dev/null +++ b/src/NUnitTests/packages.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/ScriptEngine.HostedScript/DirectiveIgnorer.cs b/src/ScriptEngine.HostedScript/DirectiveIgnorer.cs index 74aa8fc09..d825185a4 100644 --- a/src/ScriptEngine.HostedScript/DirectiveIgnorer.cs +++ b/src/ScriptEngine.HostedScript/DirectiveIgnorer.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using ScriptEngine.Environment; diff --git a/src/ScriptEngine.HostedScript/DirectiveMultiResolver.cs b/src/ScriptEngine.HostedScript/DirectiveMultiResolver.cs index b998dbe04..144b0f5af 100644 --- a/src/ScriptEngine.HostedScript/DirectiveMultiResolver.cs +++ b/src/ScriptEngine.HostedScript/DirectiveMultiResolver.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using ScriptEngine.Environment; diff --git a/src/ScriptEngine.HostedScript/EngineConfigProvider.cs b/src/ScriptEngine.HostedScript/EngineConfigProvider.cs index 8a39c5177..78b92f48e 100644 --- a/src/ScriptEngine.HostedScript/EngineConfigProvider.cs +++ b/src/ScriptEngine.HostedScript/EngineConfigProvider.cs @@ -6,6 +6,7 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; +using System.Collections; using System.Collections.Generic; using System.IO; using System.Linq; @@ -104,12 +105,24 @@ private void ReadCustomConfig() } } + private void ReadEnvironmentOverrides() + { + var env = System.Environment.GetEnvironmentVariable("OSCRIPT_CONFIG"); + if(env == null) + return; + + var paramList = new FormatParametersList(env); + _currentConfig.Merge(paramList.ToDictionary()); + } + public KeyValueConfig ReadConfig() { ReadDefaultConfig(); ReadCustomConfig(); + ReadEnvironmentOverrides(); return _currentConfig; } + } } diff --git a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs index 8847432c5..c736947a5 100644 --- a/src/ScriptEngine.HostedScript/HostedScriptEngine.cs +++ b/src/ScriptEngine.HostedScript/HostedScriptEngine.cs @@ -208,7 +208,7 @@ public Process CreateProcess(IHostApplication host, ScriptModuleHandle moduleHan return InitProcess(host, ref module); } - private void SetGlobalEnvironment(IHostApplication host, ICodeSource src) + public void SetGlobalEnvironment(IHostApplication host, ICodeSource src) { _globalCtx.ApplicationHost = host; _globalCtx.CodeSource = src; @@ -223,15 +223,20 @@ private Process InitProcess(IHostApplication host, ref LoadedModuleHandle module return process; } - public void EnableCodeStatistics(string outputFileName) + public void EnableCodeStatistics() { - _codeStat = new CodeStatProcessor(outputFileName); + _codeStat = new CodeStatProcessor(); _engine.SetCodeStatisticsCollector(_codeStat); } + public CodeStatDataCollection GetCodeStatData() + { + return _codeStat.GetStatData(); + } + public void Finalize() { - _codeStat?.OutputCodeStat(); + _codeStat?.EndCodeStat(); } } } diff --git a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs index 952de8721..d02623ae3 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/BinaryDataBuffer.cs @@ -1,4 +1,10 @@ - +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + using System; using System.Collections.Generic; using System.IO; @@ -514,4 +520,4 @@ public void ThrowIfReadonly() if (_readOnly) throw new RuntimeException("Буфер находится в режиме \"Только чтение\""); } -} \ No newline at end of file +} diff --git a/src/ScriptEngine.HostedScript/Library/Binary/DataReader.cs b/src/ScriptEngine.HostedScript/Library/Binary/DataReader.cs index 871240f51..768c2267b 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/DataReader.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/DataReader.cs @@ -1,4 +1,10 @@ - +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + //using System; //using ScriptEngine.Machine; //using ScriptEngine.Machine.Contexts; @@ -18,11 +24,16 @@ //[ContextClass("ЧтениеДанных", "DataReader")] //class DataReader : AutoContext //{ - //private IValue _TextEncoding - //private string _ConvertibleSplitterOfLines - //private IValue _ByteOrder - //private string _LineSplitter - //private bool _ReadCompleted + +//private IValue _TextEncoding + +//private string _ConvertibleSplitterOfLines + +//private IValue _ByteOrder + +//private string _LineSplitter + +//private bool _ReadCompleted //public DataReader() //{ @@ -4740,4 +4751,4 @@ // return null; //} -//} \ No newline at end of file +//} diff --git a/src/ScriptEngine.HostedScript/Library/Binary/DataWriter.cs b/src/ScriptEngine.HostedScript/Library/Binary/DataWriter.cs index db10b21a4..ca5c33a1f 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/DataWriter.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/DataWriter.cs @@ -1,4 +1,10 @@ - +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + //using System; //using ScriptEngine.Machine; //using ScriptEngine.Machine.Contexts; @@ -19,10 +25,14 @@ //[ContextClass("ЗаписьДанных", "DataWriter")] //class DataWriter : AutoContext //{ - //private IValue _TextEncoding - //private string _ConvertibleSplitterOfLines - //private IValue _ByteOrder - //private string _LineSplitter + +//private IValue _TextEncoding + +//private string _ConvertibleSplitterOfLines + +//private IValue _ByteOrder + +//private string _LineSplitter //public DataWriter() //{ @@ -1811,4 +1821,4 @@ // return null; //} -//} \ No newline at end of file +//} diff --git a/src/ScriptEngine.HostedScript/Library/Binary/EndianBitConverter.cs b/src/ScriptEngine.HostedScript/Library/Binary/EndianBitConverter.cs index bc86ef2ba..2a7b02e20 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/EndianBitConverter.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/EndianBitConverter.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -721,4 +727,4 @@ public ulong ToUInt64(byte[] value, int startIndex) } } } -} \ No newline at end of file +} diff --git a/src/ScriptEngine.HostedScript/Library/Binary/FileStreamContext.cs b/src/ScriptEngine.HostedScript/Library/Binary/FileStreamContext.cs index 6d06823f5..286bc131e 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/FileStreamContext.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/FileStreamContext.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.IO; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -287,4 +293,4 @@ public static FileStreamContext Constructor(IValue filename, IValue openMode, IV ContextValuesMarshaller.ConvertParam(bufferSize)); } } -} \ No newline at end of file +} diff --git a/src/ScriptEngine.HostedScript/Library/Binary/FileStreamsManager.cs b/src/ScriptEngine.HostedScript/Library/Binary/FileStreamsManager.cs index c297ac45c..ed8131456 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/FileStreamsManager.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/FileStreamsManager.cs @@ -1,4 +1,10 @@ - +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + using System; using System.IO; @@ -180,4 +186,4 @@ public IValue CreateTempFile(int MemoryLimit = 0, int BufferSize = 0) throw new NotImplementedException(); } -} \ No newline at end of file +} diff --git a/src/ScriptEngine.HostedScript/Library/Binary/GenericStream.cs b/src/ScriptEngine.HostedScript/Library/Binary/GenericStream.cs index 067e0d8c9..80ba5c010 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/GenericStream.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/GenericStream.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.IO; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -245,4 +251,4 @@ public Stream GetUnderlyingStream() return _underlyingStream; } } -} \ No newline at end of file +} diff --git a/src/ScriptEngine.HostedScript/Library/Binary/GenericStreamImpl.cs b/src/ScriptEngine.HostedScript/Library/Binary/GenericStreamImpl.cs index c8c117543..d515e808f 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/GenericStreamImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/GenericStreamImpl.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.CodeDom; using System.Collections.Generic; using System.IO; diff --git a/src/ScriptEngine.HostedScript/Library/Binary/MemoryStreamContext.cs b/src/ScriptEngine.HostedScript/Library/Binary/MemoryStreamContext.cs index 48f2c6908..c97f26c3c 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/MemoryStreamContext.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/MemoryStreamContext.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.IO; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; diff --git a/src/ScriptEngine.HostedScript/Library/Binary/ReadDataResult.cs b/src/ScriptEngine.HostedScript/Library/Binary/ReadDataResult.cs index aac19c237..0ff4655d6 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/ReadDataResult.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/ReadDataResult.cs @@ -1,4 +1,10 @@ - +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + //using System; //using ScriptEngine.Machine; //using ScriptEngine.Machine.Contexts; @@ -168,4 +174,4 @@ // return null; //} -//} \ No newline at end of file +//} diff --git a/src/ScriptEngine.HostedScript/Library/Binary/StreamEnums.cs b/src/ScriptEngine.HostedScript/Library/Binary/StreamEnums.cs index 4d98e0678..a35f9add0 100644 --- a/src/ScriptEngine.HostedScript/Library/Binary/StreamEnums.cs +++ b/src/ScriptEngine.HostedScript/Library/Binary/StreamEnums.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/ScriptEngine.HostedScript/Library/CommandLineArguments.cs b/src/ScriptEngine.HostedScript/Library/CommandLineArguments.cs deleted file mode 100644 index 91932abea..000000000 --- a/src/ScriptEngine.HostedScript/Library/CommandLineArguments.cs +++ /dev/null @@ -1,118 +0,0 @@ -/*---------------------------------------------------------- -This Source Code Form is subject to the terms of the -Mozilla Public License, v.2.0. If a copy of the MPL -was not distributed with this file, You can obtain one -at http://mozilla.org/MPL/2.0/. -----------------------------------------------------------*/ -using System; -using System.Collections.Generic; -using System.Linq; - -using ScriptEngine.Machine; -using ScriptEngine.Machine.Contexts; - -namespace ScriptEngine.HostedScript.Library -{ - /// - /// Коллекция позволяет получить аргументы, переданные сценарию в командной строке. - /// Коллекция представляет собой массив в режиме "ТолькоДляЧтения". Обращение к аргументам осуществляется по порядковому индексу. - /// - [ContextClass("КоллекцияАргументовКоманднойСтроки", "CommandLineArgumentsCollection")] - class CommandLineArguments : ContextIValueImpl, ICollectionContext - { - private readonly string[] _values; - - public CommandLineArguments(string[] arguments) - { - _values = arguments; - } - - public override bool IsIndexed - { - get - { - return true; - } - } - - public override IValue GetIndexedValue(IValue index) - { - var arrIdx = (int)index.AsNumber(); - return ValueFactory.Create(_values[arrIdx]); - } - - public override void SetIndexedValue(IValue index, IValue val) - { - throw new RuntimeException("Коллекция предназначена только для чтения"); - } - - public override int FindMethod(string name) - { - if (name.ToLower() == "количество" || name.ToLower() == "count") - { - return 0; - } - else - throw RuntimeException.MethodNotFoundException(name); - } - - public override IEnumerable GetMethods() - { - yield return GetMethodInfo(0); - } - - public override void CallAsFunction(int methodNumber, IValue[] arguments, out IValue retValue) - { - if (methodNumber == 0) - retValue = ValueFactory.Create(this.Count()); - else - retValue = null; - } - - public override void CallAsProcedure(int methodNumber, IValue[] arguments) - { - } - - public override MethodInfo GetMethodInfo(int methodNumber) - { - if (methodNumber == 0) - return new MethodInfo() - { - Name = "количество", - Alias = "count", - IsFunction = true, - Params = new ParameterDefinition[0] - }; - else - throw new InvalidOperationException(); - } - - - #region ICollectionContext Members - - public int Count() - { - return _values.Length; - } - - public void Clear() - { - throw new RuntimeException("Коллекция предназначена только для чтения"); - } - - public CollectionEnumerator GetManagedIterator() - { - return new CollectionEnumerator(_values.Select(x=>ValueFactory.Create(x))); - } - - #endregion - - - private static readonly CommandLineArguments _empty = new CommandLineArguments(new string[0]); - - public static CommandLineArguments Empty - { - get { return _empty; } - } - } -} diff --git a/src/ScriptEngine.HostedScript/Library/ConsoleColorEnum.cs b/src/ScriptEngine.HostedScript/Library/ConsoleColorEnum.cs index 7e5709b5e..01bf348f4 100644 --- a/src/ScriptEngine.HostedScript/Library/ConsoleColorEnum.cs +++ b/src/ScriptEngine.HostedScript/Library/ConsoleColorEnum.cs @@ -15,7 +15,7 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library { [SystemEnum("ЦветКонсоли", "ConsoleColor")] - class ConsoleColorEnum : EnumerationContext + public class ConsoleColorEnum : EnumerationContext { readonly Dictionary _valuesCache = new Dictionary(); diff --git a/src/ScriptEngine.HostedScript/Library/ConsoleContext.cs b/src/ScriptEngine.HostedScript/Library/ConsoleContext.cs index 2ee24f0de..4b939fa83 100644 --- a/src/ScriptEngine.HostedScript/Library/ConsoleContext.cs +++ b/src/ScriptEngine.HostedScript/Library/ConsoleContext.cs @@ -19,7 +19,7 @@ namespace ScriptEngine.HostedScript.Library /// Предназначен для низкоуровнего манипулирования выводом в консоль. /// [ContextClass("Консоль", "Console")] - class ConsoleContext : AutoContext + public class ConsoleContext : AutoContext { [ContextProperty("НажатаКлавиша", "KeyPressed")] public bool HasKey @@ -159,6 +159,15 @@ public IValue InputEncoding } } + /// + /// Воспроизводит звуковой сигнал. + /// + [ContextMethod("Сигнал")] + public void Beep() + { + Console.Beep(); + } + [ScriptConstructor] public static IRuntimeContextInstance Constructor() { diff --git a/src/ScriptEngine.HostedScript/Library/DriveInfo/DriveInfo.cs b/src/ScriptEngine.HostedScript/Library/DriveInfo/DriveInfo.cs new file mode 100644 index 000000000..11c2c0593 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/DriveInfo/DriveInfo.cs @@ -0,0 +1,145 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.HostedScript.Library; +using ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; +using System; + +namespace ScriptEngine.HostedScript.Library.DriveInfo +{ + [ContextClass("ИнформацияОДиске", "DriveInfo")] + public class DriveInfo : AutoContext + { + private System.IO.DriveInfo _driveInfo; + + public DriveInfo(string driveName) + { + SystemDriveInfo = new System.IO.DriveInfo(driveName); + } + + [ScriptConstructor] + public static IRuntimeContextInstance Constructor(IValue driveName) + { + return new DriveInfo(driveName.AsString()); + } + + + /// + /// Указывает объем доступного свободного места на диске в байтах. + /// + [ContextProperty("Доступно")] + public Int64 AvailableFreeSpace + { + get { return SystemDriveInfo.AvailableFreeSpace; } + } + + /// + /// Получает имя файловой системы + /// + [ContextProperty("ИмяФС")] + public string DriveFormat + { + get { return SystemDriveInfo.DriveFormat; } + } + + /// + /// Возвращает тип диска + /// + /// ТипДиска + [ContextProperty("ТипДиска", "DriveType")] + public IValue DriveTypeProp + { + get { + var dte = DriveTypeEnum.CreateInstance(); + return dte.GetPropValue((int)_driveInfo.DriveType); + } + } + + /// + /// Получает значение, указывающее состояние готовности диска. + /// + [ContextProperty("Готов")] + public bool IsReady + { + get + { + return SystemDriveInfo.IsReady; + } + } + + /// + /// Возвращает имя диска + /// + [ContextProperty("Имя")] + public string Name + { + get + { + return SystemDriveInfo.Name; + } + } + + /// + /// Возвращает корневой каталог диска. + /// + [ContextProperty("КорневойКаталог")] + public IValue RootDirectory + { + get + { + return new FileContext(SystemDriveInfo.RootDirectory.FullName); + } + } + + /// + /// Возвращает общий объем свободного места, доступного на диске, в байтах + /// + [ContextProperty("ОбщийОбъемСвободногоМеста")] + public Int64 TotalFreeSpace + { + get { return SystemDriveInfo.TotalFreeSpace; } + } + + /// + /// Возвращает общий размер места для хранения на диске в байтах. + /// + [ContextProperty("РазмерДиска")] + public Int64 TotalSize + { + get { return SystemDriveInfo.TotalSize; } + } + + /// + /// Возвращает или задает метку тома диска. + /// + [ContextProperty("МеткаТома")] + public string VolumeLabel + { + get + { + return SystemDriveInfo.VolumeLabel; + } + set + { + SystemDriveInfo.VolumeLabel = value; + } + } + + public System.IO.DriveInfo SystemDriveInfo + { + get + { + return _driveInfo; + } + + set + { + _driveInfo = value; + } + } + } +} diff --git a/src/ScriptEngine.HostedScript/Library/DriveInfo/DriveTypeEnum.cs b/src/ScriptEngine.HostedScript/Library/DriveInfo/DriveTypeEnum.cs new file mode 100644 index 000000000..9c40f7ba0 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/DriveInfo/DriveTypeEnum.cs @@ -0,0 +1,53 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine.Contexts; +using ScriptEngine.Machine; + +namespace ScriptEngine.HostedScript.Library.DriveInfo +{ + /// + /// Типы дисков: + /// - Диск является устройством оптических дисков, такие как компакт-ДИСК или DVD-диск. + /// - Диск является жестким диском. + /// - Диск является сетевым диском. + /// - Диск не имеет корневой каталог. + /// - Диск является диском ОЗУ. + /// - Диск является съемное запоминающее устройство, например, дисковод гибких дисков или USB-устройство флэш-памяти. + /// - Тип диска неизвестен. + /// + [SystemEnum("ТипДиска", "DriveType")] + public class DriveTypeEnum : EnumerationContext + { + + private DriveTypeEnum(TypeDescriptor typeRepresentation, TypeDescriptor valuesType) + : base(typeRepresentation, valuesType) + { + + } + + public static DriveTypeEnum CreateInstance() + { + DriveTypeEnum instance; + var type = TypeManager.RegisterType("ПеречислениеТипДиска", typeof(DriveTypeEnum)); + var enumValueType = TypeManager.RegisterType("ТипДиска", typeof(CLREnumValueWrapper)); + + instance = new DriveTypeEnum(type, enumValueType); + + instance.AddValue("Неизвестный", "Unknown", new CLREnumValueWrapper(instance, System.IO.DriveType.Unknown)); + instance.AddValue("НеИмеетКорневойКаталог", "NoRootDirectory", new CLREnumValueWrapper(instance, System.IO.DriveType.NoRootDirectory)); + instance.AddValue("СъемноеЗапоминающееУстройство", "Removable", new CLREnumValueWrapper(instance, System.IO.DriveType.Removable)); + instance.AddValue("ЖесткийДиск", "Fixed", new CLREnumValueWrapper(instance, System.IO.DriveType.Fixed)); + instance.AddValue("СетевойДиск", "Network", new CLREnumValueWrapper(instance, System.IO.DriveType.Network)); + instance.AddValue("ОптическийДиск", "CDRom", new CLREnumValueWrapper(instance, System.IO.DriveType.CDRom)); + instance.AddValue("ДискОЗУ", "Ram", new CLREnumValueWrapper(instance, System.IO.DriveType.Ram)); + + return instance; + } + + } + +} diff --git a/src/ScriptEngine.HostedScript/Library/EnvironmentVariablesImpl.cs b/src/ScriptEngine.HostedScript/Library/EnvironmentVariablesImpl.cs new file mode 100644 index 000000000..13fd55791 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/EnvironmentVariablesImpl.cs @@ -0,0 +1,79 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ScriptEngine.HostedScript.Library +{ + [GlobalContext(Category = "Работа с переменными окружения")] + public class EnvironmentVariablesImpl : GlobalContextBase + { + + /// + /// Возвращает соответствие переменных среды. Ключом является имя переменной, а значением - значение переменной + /// + /// + /// Для Каждого Переменная Из ПеременныеСреды() Цикл + /// Сообщить(Переменная.Ключ + " = " + Переменная.Значение); + /// КонецЦикла; + /// + /// Соответствие + [ContextMethod("ПеременныеСреды", "EnvironmentVariables")] + public IRuntimeContextInstance EnvironmentVariables() + { + var varsMap = new MapImpl(); + var allVars = System.Environment.GetEnvironmentVariables(); + foreach (DictionaryEntry item in allVars) + { + varsMap.Insert( + ValueFactory.Create((string)item.Key), + ValueFactory.Create((string)item.Value)); + } + + return varsMap; + } + + /// + /// Позволяет установить переменную среды. + /// Переменная устанавливается в области видимости процесса и очищается после его завершения. + /// + /// Имя переменной + /// Значение переменной + [ContextMethod("УстановитьПеременнуюСреды", "SetEnvironmentVariable")] + public void SetEnvironmentVariable(string varName, string value) + { + System.Environment.SetEnvironmentVariable(varName, value); + } + + /// + /// Получить значение переменной среды. + /// + /// Имя переменной + /// Строка. Значение переменной + [ContextMethod("ПолучитьПеременнуюСреды", "GetEnvironmentVariable")] + public IValue GetEnvironmentVariable(string varName) + { + string value = System.Environment.GetEnvironmentVariable(varName); + if (value == null) + return ValueFactory.Create(); + else + return ValueFactory.Create(value); + + } + + public static IAttachableContext CreateInstance() + { + return new EnvironmentVariablesImpl(); + } + } +} diff --git a/src/ScriptEngine.HostedScript/Library/FileOperations.cs b/src/ScriptEngine.HostedScript/Library/FileOperations.cs index c65053100..ed265f54e 100644 --- a/src/ScriptEngine.HostedScript/Library/FileOperations.cs +++ b/src/ScriptEngine.HostedScript/Library/FileOperations.cs @@ -204,6 +204,10 @@ public void DeleteFiles(string path, string mask = "") } else { + // bugfix #419 + if (!Directory.Exists(path)) + return; + var entries = System.IO.Directory.EnumerateFileSystemEntries(path, mask) .AsParallel() .ToArray(); diff --git a/src/ScriptEngine.HostedScript/Library/FixedArrayImpl.cs b/src/ScriptEngine.HostedScript/Library/FixedArrayImpl.cs index bff13427b..d5509d294 100644 --- a/src/ScriptEngine.HostedScript/Library/FixedArrayImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/FixedArrayImpl.cs @@ -1,7 +1,7 @@ /*---------------------------------------------------------- -This Source Code Form is subject to the terms of the -Mozilla Public License, v.2.0. If a copy of the MPL -was not distributed with this file, You can obtain one +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System; diff --git a/src/ScriptEngine.HostedScript/Library/FixedStructureImpl.cs b/src/ScriptEngine.HostedScript/Library/FixedStructureImpl.cs index 888da444d..6d7c3b83b 100644 --- a/src/ScriptEngine.HostedScript/Library/FixedStructureImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/FixedStructureImpl.cs @@ -1,7 +1,7 @@ /*---------------------------------------------------------- -This Source Code Form is subject to the terms of the -Mozilla Public License, v.2.0. If a copy of the MPL -was not distributed with this file, You can obtain one +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System.Collections.Generic; diff --git a/src/ScriptEngine.HostedScript/Library/Hash/Crc32.cs b/src/ScriptEngine.HostedScript/Library/Hash/Crc32.cs index f445e83dc..598a1b71c 100644 --- a/src/ScriptEngine.HostedScript/Library/Hash/Crc32.cs +++ b/src/ScriptEngine.HostedScript/Library/Hash/Crc32.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/ScriptEngine.HostedScript/Library/Hash/HashFunctionEnum.cs b/src/ScriptEngine.HostedScript/Library/Hash/HashFunctionEnum.cs index 461a1d3f7..931b34299 100644 --- a/src/ScriptEngine.HostedScript/Library/Hash/HashFunctionEnum.cs +++ b/src/ScriptEngine.HostedScript/Library/Hash/HashFunctionEnum.cs @@ -16,7 +16,7 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library.Hash { [SystemEnum("ХешФункция", "HashFunction")] - class HashFunctionEnum : EnumerationContext + public class HashFunctionEnum : EnumerationContext { const string MD5 = "MD5"; const string SHA1 = "SHA1"; diff --git a/src/ScriptEngine.HostedScript/Library/Hash/HashImpl.cs b/src/ScriptEngine.HostedScript/Library/Hash/HashImpl.cs index 692088529..0dd8d00b9 100644 --- a/src/ScriptEngine.HostedScript/Library/Hash/HashImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/Hash/HashImpl.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -12,7 +18,7 @@ namespace ScriptEngine.HostedScript.Library.Hash { [ContextClass("ХешированиеДанных", "DataHashing")] - class HashImpl: AutoContext + public class HashImpl : AutoContext { protected HashAlgorithm _provider; protected IValue _enumValue; diff --git a/src/ScriptEngine.HostedScript/Library/Http/HttpConnectionContext.cs b/src/ScriptEngine.HostedScript/Library/Http/HttpConnectionContext.cs index cbf4e17b6..c680213f8 100644 --- a/src/ScriptEngine.HostedScript/Library/Http/HttpConnectionContext.cs +++ b/src/ScriptEngine.HostedScript/Library/Http/HttpConnectionContext.cs @@ -1,408 +1,415 @@ -/*---------------------------------------------------------- -This Source Code Form is subject to the terms of the -Mozilla Public License, v.2.0. If a copy of the MPL -was not distributed with this file, You can obtain one -at http://mozilla.org/MPL/2.0/. -----------------------------------------------------------*/ -using ScriptEngine.Machine; -using ScriptEngine.Machine.Contexts; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Net; -using System.Text; - -namespace ScriptEngine.HostedScript.Library.Http -{ - /// - /// Объект доступа к протоколу HTTP/HTTPS. - /// Использует семантику методов, реализованных в платформе 1С:Предприятие 8.2.18 и старше. - /// Синтаксис методов, применявшийся в более младших версиях не поддерживается. - /// Средства работы с HTTP находятся в статусе experimental. - /// - [ContextClass("HTTPСоединение", "HTTPConnection")] - public class HttpConnectionContext : AutoContext - { - readonly InternetProxyContext _proxy; - - readonly Uri _hostUri; - - const string HTTP_SCHEME = "http"; - const string HTTPS_SCHEME = "https"; - - public HttpConnectionContext(string host, - int port = 0, - string user = null, - string password = null, - InternetProxyContext proxy = null, - int timeout = 0, - IValue ssl = null, - bool useOSAuth = false) - { - if (ssl != null && !(ssl.DataType == Machine.DataType.Undefined || ssl.DataType == Machine.DataType.NotAValidValue)) - throw new RuntimeException("Защищенное соединение по произвольным сертификатам не поддерживается. Если необходим доступ по https, просто укажите протокол https в адресе хоста."); - - var uriBuilder = new UriBuilder(host); - if (port != 0) - uriBuilder.Port = port; - - if (uriBuilder.Scheme != HTTP_SCHEME && uriBuilder.Scheme != HTTPS_SCHEME) - throw RuntimeException.InvalidArgumentValue(); - - _hostUri = uriBuilder.Uri; - - Host = _hostUri.Host; - Port = _hostUri.Port; - - User = user == null ? String.Empty : user; - Password = password == null ? String.Empty : password; - Timeout = timeout; - _proxy = proxy; - UseOSAuthentication = useOSAuth; - - } - - [ContextProperty("ИспользоватьАутентификациюОС", "UseOSAuthentication", CanWrite=false)] - public bool UseOSAuthentication - { - get; - set; - } - - [ContextProperty("Пользователь","User")] - public string User - { - get; private set; - } - - [ContextProperty("Пароль", "Password")] - public string Password - { - get; private set; - - } - - [ContextProperty("Сервер", "Host")] - public string Host - { - get; private set; - } - - [ContextProperty("Порт", "Port")] - public int Port - { - get; private set; - } - - [ContextProperty("Прокси", "Proxy")] - public IValue Proxy - { - get - { - if (_proxy == null) - return ValueFactory.Create(); - - return _proxy; - } - } - - [ContextProperty("Таймаут", "Timeout")] - public int Timeout - { - get; private set; - } - - /// - /// Получить данные методом GET - /// - /// HTTPЗапрос. Данные и заголовки запроса http - /// Строка. Имя файла, в который нужно записать ответ. Необязательный параметр. - /// HTTPОтвет. Ответ сервера. - [ContextMethod("Получить", "Get")] - public HttpResponseContext Get(HttpRequestContext request, string output = null) - { - return GetResponse(request, "GET", output); - } - - /// - /// Передача данных методом PUT - /// - /// HTTPЗапрос. Данные и заголовки запроса http - /// HTTPОтвет. Ответ сервера. - [ContextMethod("Записать", "Put")] - public HttpResponseContext Put(HttpRequestContext request) - { - return GetResponse(request, "PUT"); - } - - /// - /// Передача данных методом POST - /// - /// HTTPЗапрос. Данные и заголовки запроса http - /// Строка. Имя файла, в который нужно записать ответ. Необязательный параметр. - /// HTTPОтвет. Ответ сервера. - [ContextMethod("ОтправитьДляОбработки", "Post")] - public HttpResponseContext Post(HttpRequestContext request, string output = null) - { - return GetResponse(request, "POST", output); - } - - /// - /// Удалить данные методом DELETE - /// - /// HTTPЗапрос. Данные и заголовки запроса http - /// HTTPОтвет. Ответ сервера. - [ContextMethod("Удалить", "Delete")] - public HttpResponseContext Delete(HttpRequestContext request) - { - return GetResponse(request, "DELETE"); - } - - /// - /// Изменяет данные на сервере при помощи PATCH-запроса - /// - /// HTTPЗапрос. Данные и заголовки запроса http - /// HTTPОтвет. Ответ сервера. - [ContextMethod("Изменить", "Patch")] - public HttpResponseContext Patch(HttpRequestContext request) - { - return GetResponse(request, "PATCH"); - } - - /// - /// Получает при помощи HEAD-запроса информацию о запрошиваемых данных, содержащуюся в заголовках, не получая сами данные. - /// - /// HTTPЗапрос. Данные и заголовки запроса http - /// HTTPОтвет. Ответ сервера. - [ContextMethod("ПолучитьЗаголовки", "Head")] - public HttpResponseContext Head(HttpRequestContext request) - { - return GetResponse(request, "HEAD"); - } - - /// - /// Вызвать произвольный HTTP-метод - /// - /// Строка. Имя метода HTTP - /// HTTPЗапрос. Данные и заголовки запроса http - /// Строка. Имя выходного файла - /// HTTPОтвет. Ответ сервера. - [ContextMethod("ВызватьHTTPМетод", "CallHTTPMethod")] - public HttpResponseContext Patch(string method, HttpRequestContext request, string output = null) - { - return GetResponse(request, method, output); - } - - private HttpWebRequest CreateRequest(string resource) - { - var uriBuilder = new UriBuilder(_hostUri); - if(Port != 0) - uriBuilder.Port = Port; - - var resourceUri = new Uri(uriBuilder.Uri, resource); - - var request = (HttpWebRequest)HttpWebRequest.Create(resourceUri); - if (User != "" || Password != "") - { - request.Credentials = new NetworkCredential(User, Password); - //request.PreAuthenticate = true; - // Авторизация на сервере 1С:Предприятие, например, не работает без явного указания заголовка. - // http://blog.kowalczyk.info/article/at3/Forcing-basic-http-authentication-for-HttpWebReq.html - string authInfo = User + ":" + Password; - // Для 1С работает только UTF-8, хотя стандарт требует ISO-8859-1 - var basicAuthEncoding = Encoding.GetEncoding("UTF-8"); - authInfo = Convert.ToBase64String(basicAuthEncoding.GetBytes(authInfo)); - request.Headers["Authorization"] = "Basic " + authInfo; - } - else if(UseOSAuthentication) - { - request.Credentials = CredentialCache.DefaultNetworkCredentials; - } - - if(_proxy != null) - request.Proxy = _proxy.GetProxy(uriBuilder.Scheme); - - if (Timeout > 0) - request.Timeout = Timeout; - - return request; - - } - - private HttpResponseContext GetResponse(HttpRequestContext request, string method, string output = null) - { - var webRequest = CreateRequest(request.ResourceAddress); - webRequest.Method = method; - webRequest.KeepAlive = false; - SetRequestHeaders(request, webRequest); - SetRequestBody(request, webRequest); - - HttpWebResponse response; - - try - { - response = (HttpWebResponse)webRequest.GetResponse(); - } - catch (WebException ex) - { - if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null) - response = (HttpWebResponse)ex.Response; - else - throw; - } - - var responseContext = new HttpResponseContext(response, output); - - return responseContext; - - } - - private static void SetRequestBody(HttpRequestContext request, HttpWebRequest webRequest) - { - var stream = request.Body; - if (stream == null) - { - return; // тело не установлено - } - - using(stream) - { - if (stream.CanSeek) - webRequest.ContentLength = stream.Length; - - using(var requestStream = webRequest.GetRequestStream()) - { - const int CHUNK_SIZE = 4096; - byte[] buf = new byte[CHUNK_SIZE]; - - while(true) - { - int bytesRead = stream.Read(buf, 0, CHUNK_SIZE); - if (bytesRead == 0) - break; - - requestStream.Write(buf, 0, bytesRead); - - } - } - } - } - - private static void SetRequestHeaders(HttpRequestContext request, HttpWebRequest webRequest) - { - foreach (var item in request.Headers.Select(x => x.GetRawValue() as KeyAndValueImpl)) - { - System.Diagnostics.Trace.Assert(item != null); - - var key = item.Key.AsString(); - var value = item.Value.AsString(); - - switch(key.ToUpperInvariant()) - { - case "CONTENT-TYPE": - webRequest.ContentType = value; - break; - case "CONTENT-LENGTH": - try - { - webRequest.ContentLength = Int32.Parse(value); - } - catch (FormatException) - { - throw new RuntimeException("Заголовок Content-Length задан неправильно"); - } - break; - case "ACCEPT": - webRequest.Accept = value; - break; - case "EXPECT": - webRequest.Expect = value; - break; - case "TRANSFER-ENCODING": - webRequest.TransferEncoding = value; - break; - case "CONNECTION": - webRequest.Connection = value; - break; - case "DATE": - try - { - webRequest.Date = DateTime.Parse(value); - } - catch (FormatException) - { - throw new RuntimeException("Заголовок Date задан неправильно"); - } - break; - case "HOST": - webRequest.Host = value; - break; - case "IF-MODIFIED-SINCE": - try - { - webRequest.IfModifiedSince = DateTime.Parse(value); - } - catch (FormatException) - { - throw new RuntimeException("Заголовок If-Modified-Since задан неправильно"); - } - break; - case "RANGE": - throw new NotImplementedException(); - case "REFERER": - webRequest.Referer = value; - break; - case "USER-AGENT": - webRequest.UserAgent = value; - break; - case "PROXY-CONNECTION": - throw new NotImplementedException(); - default: - webRequest.Headers.Set(key, value); - break; - - } - - - - } - } - - /// - /// Стандартный конструктор. Поддержка клиентских сертификатов HTTPS в текущей версии не реализована. - /// Для доступа к серверу по протоколу HTTPS указывайте схему https:// в URL. - /// - /// Адрес сервера (можно указать URL-схему http или https) - /// Порт сервера - /// Пользователь - /// Пароль - /// ИнтернетПрокси. Настройки прокси-сервера - /// Таймаут ожидания. - /// Объект ЗащищенноеСоединение. На данный момент данная механика работы с SSL не поддерживается. - /// Обращение к https возможно, если в адресе хоста указать протокол https. В этом случае будут использованы сертификаты из хранилища ОС. +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Text; + +namespace ScriptEngine.HostedScript.Library.Http +{ + /// + /// Объект доступа к протоколу HTTP/HTTPS. + /// Использует семантику методов, реализованных в платформе 1С:Предприятие 8.2.18 и старше. + /// Синтаксис методов, применявшийся в более младших версиях не поддерживается. + /// Средства работы с HTTP находятся в статусе experimental. + /// + [ContextClass("HTTPСоединение", "HTTPConnection")] + public class HttpConnectionContext : AutoContext + { + readonly InternetProxyContext _proxy; + + readonly Uri _hostUri; + + const string HTTP_SCHEME = "http"; + const string HTTPS_SCHEME = "https"; + + public HttpConnectionContext(string host, + int port = 0, + string user = null, + string password = null, + InternetProxyContext proxy = null, + int timeout = 0, + IValue ssl = null, + bool useOSAuth = false) + { + if (ssl != null && !(ssl.DataType == Machine.DataType.Undefined || ssl.DataType == Machine.DataType.NotAValidValue)) + throw new RuntimeException("Защищенное соединение по произвольным сертификатам не поддерживается. Если необходим доступ по https, просто укажите протокол https в адресе хоста."); + + var uriBuilder = new UriBuilder(host); + if (port != 0) + uriBuilder.Port = port; + + if (uriBuilder.Scheme != HTTP_SCHEME && uriBuilder.Scheme != HTTPS_SCHEME) + throw RuntimeException.InvalidArgumentValue(); + + _hostUri = uriBuilder.Uri; + + Host = _hostUri.Host; + Port = _hostUri.Port; + + User = user == null ? String.Empty : user; + Password = password == null ? String.Empty : password; + + Timeout = timeout; + _proxy = proxy; + UseOSAuthentication = useOSAuth; + + } + + [ContextProperty("ИспользоватьАутентификациюОС", "UseOSAuthentication", CanWrite=false)] + public bool UseOSAuthentication + { + get; + set; + } + + [ContextProperty("Пользователь","User")] + public string User + { + get; private set; + } + + [ContextProperty("Пароль", "Password")] + public string Password + { + get; private set; + + } + + [ContextProperty("Сервер", "Host")] + public string Host + { + get; private set; + } + + [ContextProperty("Порт", "Port")] + public int Port + { + get; private set; + } + + [ContextProperty("Прокси", "Proxy")] + public IValue Proxy + { + get + { + if (_proxy == null) + return ValueFactory.Create(); + + return _proxy; + } + } + + [ContextProperty("Таймаут", "Timeout")] + public int Timeout + { + get; private set; + } + + /// + /// Получить данные методом GET + /// + /// HTTPЗапрос. Данные и заголовки запроса http + /// Строка. Имя файла, в который нужно записать ответ. Необязательный параметр. + /// HTTPОтвет. Ответ сервера. + [ContextMethod("Получить", "Get")] + public HttpResponseContext Get(HttpRequestContext request, string output = null) + { + return GetResponse(request, "GET", output); + } + + /// + /// Передача данных методом PUT + /// + /// HTTPЗапрос. Данные и заголовки запроса http + /// HTTPОтвет. Ответ сервера. + [ContextMethod("Записать", "Put")] + public HttpResponseContext Put(HttpRequestContext request) + { + return GetResponse(request, "PUT"); + } + + /// + /// Передача данных методом POST + /// + /// HTTPЗапрос. Данные и заголовки запроса http + /// Строка. Имя файла, в который нужно записать ответ. Необязательный параметр. + /// HTTPОтвет. Ответ сервера. + [ContextMethod("ОтправитьДляОбработки", "Post")] + public HttpResponseContext Post(HttpRequestContext request, string output = null) + { + return GetResponse(request, "POST", output); + } + + /// + /// Удалить данные методом DELETE + /// + /// HTTPЗапрос. Данные и заголовки запроса http + /// HTTPОтвет. Ответ сервера. + [ContextMethod("Удалить", "Delete")] + public HttpResponseContext Delete(HttpRequestContext request) + { + return GetResponse(request, "DELETE"); + } + + /// + /// Изменяет данные на сервере при помощи PATCH-запроса + /// + /// HTTPЗапрос. Данные и заголовки запроса http + /// HTTPОтвет. Ответ сервера. + [ContextMethod("Изменить", "Patch")] + public HttpResponseContext Patch(HttpRequestContext request) + { + return GetResponse(request, "PATCH"); + } + + /// + /// Получает при помощи HEAD-запроса информацию о запрошиваемых данных, содержащуюся в заголовках, не получая сами данные. + /// + /// HTTPЗапрос. Данные и заголовки запроса http + /// HTTPОтвет. Ответ сервера. + [ContextMethod("ПолучитьЗаголовки", "Head")] + public HttpResponseContext Head(HttpRequestContext request) + { + return GetResponse(request, "HEAD"); + } + + /// + /// Вызвать произвольный HTTP-метод + /// + /// Строка. Имя метода HTTP + /// HTTPЗапрос. Данные и заголовки запроса http + /// Строка. Имя выходного файла + /// HTTPОтвет. Ответ сервера. + [ContextMethod("ВызватьHTTPМетод", "CallHTTPMethod")] + public HttpResponseContext Patch(string method, HttpRequestContext request, string output = null) + { + return GetResponse(request, method, output); + } + + private HttpWebRequest CreateRequest(string resource) + { + var uriBuilder = new UriBuilder(_hostUri); + if(Port != 0) + uriBuilder.Port = Port; + + var resourceUri = new Uri(uriBuilder.Uri, resource); + + var request = (HttpWebRequest)HttpWebRequest.Create(resourceUri); + if (User != "" || Password != "") + { + request.Credentials = new NetworkCredential(User, Password); + //request.PreAuthenticate = true; + // Авторизация на сервере 1С:Предприятие, например, не работает без явного указания заголовка. + // http://blog.kowalczyk.info/article/at3/Forcing-basic-http-authentication-for-HttpWebReq.html + string authInfo = User + ":" + Password; + // Для 1С работает только UTF-8, хотя стандарт требует ISO-8859-1 + var basicAuthEncoding = Encoding.GetEncoding("UTF-8"); + authInfo = Convert.ToBase64String(basicAuthEncoding.GetBytes(authInfo)); + request.Headers["Authorization"] = "Basic " + authInfo; + } + else if(UseOSAuthentication) + { + request.Credentials = CredentialCache.DefaultNetworkCredentials; + } + + if(_proxy != null) + request.Proxy = _proxy.GetProxy(uriBuilder.Scheme); + + if (Timeout == 0) + { + request.Timeout = System.Threading.Timeout.Infinite; + } + else + { + request.Timeout = Timeout * 1000; + } + + return request; + + } + + private HttpResponseContext GetResponse(HttpRequestContext request, string method, string output = null) + { + var webRequest = CreateRequest(request.ResourceAddress); + webRequest.Method = method; + webRequest.KeepAlive = false; + SetRequestHeaders(request, webRequest); + SetRequestBody(request, webRequest); + + HttpWebResponse response; + + try + { + response = (HttpWebResponse)webRequest.GetResponse(); + } + catch (WebException ex) + { + if (ex.Status == WebExceptionStatus.ProtocolError && ex.Response != null) + response = (HttpWebResponse)ex.Response; + else + throw; + } + + var responseContext = new HttpResponseContext(response, output); + + return responseContext; + + } + + private static void SetRequestBody(HttpRequestContext request, HttpWebRequest webRequest) + { + var stream = request.Body; + if (stream == null) + { + return; // тело не установлено + } + + using(stream) + { + if (stream.CanSeek) + webRequest.ContentLength = stream.Length; + + using(var requestStream = webRequest.GetRequestStream()) + { + const int CHUNK_SIZE = 4096; + byte[] buf = new byte[CHUNK_SIZE]; + + while(true) + { + int bytesRead = stream.Read(buf, 0, CHUNK_SIZE); + if (bytesRead == 0) + break; + + requestStream.Write(buf, 0, bytesRead); + + } + } + } + } + + private static void SetRequestHeaders(HttpRequestContext request, HttpWebRequest webRequest) + { + foreach (var item in request.Headers.Select(x => x.GetRawValue() as KeyAndValueImpl)) + { + System.Diagnostics.Trace.Assert(item != null); + + var key = item.Key.AsString(); + var value = item.Value.AsString(); + + switch(key.ToUpperInvariant()) + { + case "CONTENT-TYPE": + webRequest.ContentType = value; + break; + case "CONTENT-LENGTH": + try + { + webRequest.ContentLength = Int32.Parse(value); + } + catch (FormatException) + { + throw new RuntimeException("Заголовок Content-Length задан неправильно"); + } + break; + case "ACCEPT": + webRequest.Accept = value; + break; + case "EXPECT": + webRequest.Expect = value; + break; + case "TRANSFER-ENCODING": + webRequest.TransferEncoding = value; + break; + case "CONNECTION": + webRequest.Connection = value; + break; + case "DATE": + try + { + webRequest.Date = DateTime.Parse(value); + } + catch (FormatException) + { + throw new RuntimeException("Заголовок Date задан неправильно"); + } + break; + case "HOST": + webRequest.Host = value; + break; + case "IF-MODIFIED-SINCE": + try + { + webRequest.IfModifiedSince = DateTime.Parse(value); + } + catch (FormatException) + { + throw new RuntimeException("Заголовок If-Modified-Since задан неправильно"); + } + break; + case "RANGE": + throw new NotImplementedException(); + case "REFERER": + webRequest.Referer = value; + break; + case "USER-AGENT": + webRequest.UserAgent = value; + break; + case "PROXY-CONNECTION": + throw new NotImplementedException(); + default: + webRequest.Headers.Set(key, value); + break; + + } + + + + } + } + + /// + /// Стандартный конструктор. Поддержка клиентских сертификатов HTTPS в текущей версии не реализована. + /// Для доступа к серверу по протоколу HTTPS указывайте схему https:// в URL. + /// + /// Адрес сервера (можно указать URL-схему http или https) + /// Порт сервера + /// Пользователь + /// Пароль + /// ИнтернетПрокси. Настройки прокси-сервера + /// Таймаут ожидания. + /// Объект ЗащищенноеСоединение. На данный момент данная механика работы с SSL не поддерживается. + /// Обращение к https возможно, если в адресе хоста указать протокол https. В этом случае будут использованы сертификаты из хранилища ОС. /// Указание произвольных клиентских и серверных сертификатов в текущей версии не поддерживается. - /// Использовать аутентификацию ОС. - /// - [ScriptConstructor] - public static HttpConnectionContext Constructor(IValue host, - IValue port = null, - IValue user = null, - IValue password = null, - IValue proxy = null, - IValue timeout = null, - IValue ssl = null, - IValue useOSAuthentication = null) - { - return new HttpConnectionContext(host.AsString(), - ContextValuesMarshaller.ConvertParam(port), - ContextValuesMarshaller.ConvertParam(user), - ContextValuesMarshaller.ConvertParam(password), - ContextValuesMarshaller.ConvertParam(proxy), - ContextValuesMarshaller.ConvertParam(timeout), - ContextValuesMarshaller.ConvertParam(ssl), - ContextValuesMarshaller.ConvertParam(useOSAuthentication) - ); - } - - } -} + /// Использовать аутентификацию ОС. + /// + [ScriptConstructor] + public static HttpConnectionContext Constructor(IValue host, + IValue port = null, + IValue user = null, + IValue password = null, + IValue proxy = null, + IValue timeout = null, + IValue ssl = null, + IValue useOSAuthentication = null) + { + return new HttpConnectionContext(host.AsString(), + ContextValuesMarshaller.ConvertParam(port), + ContextValuesMarshaller.ConvertParam(user), + ContextValuesMarshaller.ConvertParam(password), + ContextValuesMarshaller.ConvertParam(proxy), + ContextValuesMarshaller.ConvertParam(timeout), + ContextValuesMarshaller.ConvertParam(ssl), + ContextValuesMarshaller.ConvertParam(useOSAuthentication) + ); + } + + } +} diff --git a/src/ScriptEngine.HostedScript/Library/Http/HttpResponseBody.cs b/src/ScriptEngine.HostedScript/Library/Http/HttpResponseBody.cs index 9a0432880..1fb9e3255 100644 --- a/src/ScriptEngine.HostedScript/Library/Http/HttpResponseBody.cs +++ b/src/ScriptEngine.HostedScript/Library/Http/HttpResponseBody.cs @@ -25,7 +25,7 @@ class HttpResponseBody : IDisposable public HttpResponseBody(HttpWebResponse response, string dumpToFile) { - if (dumpToFile == null) + if (String.IsNullOrEmpty(dumpToFile)) { InitInMemoryResponse(response); } diff --git a/src/ScriptEngine.HostedScript/Library/Json/JSONCharactersEscapeMode.cs b/src/ScriptEngine.HostedScript/Library/Json/JSONCharactersEscapeMode.cs index e9d8e15ab..4a11ca6bb 100644 --- a/src/ScriptEngine.HostedScript/Library/Json/JSONCharactersEscapeMode.cs +++ b/src/ScriptEngine.HostedScript/Library/Json/JSONCharactersEscapeMode.cs @@ -1,4 +1,10 @@ -using ScriptEngine.Machine; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; namespace ScriptEngine.HostedScript.Library.Json diff --git a/src/ScriptEngine.HostedScript/Library/Json/JSONLineBreak.cs b/src/ScriptEngine.HostedScript/Library/Json/JSONLineBreak.cs index 48b71ff98..bec86b28a 100644 --- a/src/ScriptEngine.HostedScript/Library/Json/JSONLineBreak.cs +++ b/src/ScriptEngine.HostedScript/Library/Json/JSONLineBreak.cs @@ -1,4 +1,10 @@ -using ScriptEngine.Machine; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; namespace ScriptEngine.HostedScript.Library.Json diff --git a/src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs b/src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs index c15719682..3233a750b 100644 --- a/src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs +++ b/src/ScriptEngine.HostedScript/Library/Json/JSONReader.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; using System.IO; @@ -11,7 +17,7 @@ namespace ScriptEngine.HostedScript.Library.Json /// Предназначен для последовательного чтения JSON-данных из файла или строки. /// [ContextClass("ЧтениеJSON", "JSONReader")] - class JSONReader : AutoContext + public class JSONReader : AutoContext { private JsonTextReader _reader; // Объект из библиотеки Newtonsoft для работы с форматом JSON diff --git a/src/ScriptEngine.HostedScript/Library/Json/JSONValueTypeEnum.cs b/src/ScriptEngine.HostedScript/Library/Json/JSONValueTypeEnum.cs index 41594971d..dec845f5d 100644 --- a/src/ScriptEngine.HostedScript/Library/Json/JSONValueTypeEnum.cs +++ b/src/ScriptEngine.HostedScript/Library/Json/JSONValueTypeEnum.cs @@ -1,4 +1,10 @@ -using ScriptEngine.Machine; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; namespace ScriptEngine.HostedScript.Library.Json diff --git a/src/ScriptEngine.HostedScript/Library/Json/JSONWriter.cs b/src/ScriptEngine.HostedScript/Library/Json/JSONWriter.cs index 547cb1749..ca4654d12 100644 --- a/src/ScriptEngine.HostedScript/Library/Json/JSONWriter.cs +++ b/src/ScriptEngine.HostedScript/Library/Json/JSONWriter.cs @@ -1,4 +1,10 @@ - +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + using System; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -15,7 +21,7 @@ namespace ScriptEngine.HostedScript.Library.Json /// Предназначен для организации последовательной записи объектов и текстов JSON. /// [ContextClass("ЗаписьJSON", "JSONWriter")] - class JSONWriter : AutoContext + public class JSONWriter : AutoContext { private const int INDENT_SIZE = 0; @@ -429,4 +435,4 @@ public void SetString(IValue settings = null) } } -} \ No newline at end of file +} diff --git a/src/ScriptEngine.HostedScript/Library/Json/JSONWriterSettings.cs b/src/ScriptEngine.HostedScript/Library/Json/JSONWriterSettings.cs index 8713c3f0a..bf1ecbada 100644 --- a/src/ScriptEngine.HostedScript/Library/Json/JSONWriterSettings.cs +++ b/src/ScriptEngine.HostedScript/Library/Json/JSONWriterSettings.cs @@ -1,4 +1,10 @@ - +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + using System; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -10,7 +16,7 @@ /// Определяет набор параметров, используемых при записи JSON. /// [ContextClass("ПараметрыЗаписиJSON", "JSONWriterSettings")] -class JSONWriterSettings : AutoContext +public class JSONWriterSettings : AutoContext { private bool _useDoubleQuotes; @@ -231,4 +237,4 @@ public bool EscapeAngleBrackets } -} \ No newline at end of file +} diff --git a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs index 8c5ede759..8f1a67624 100644 --- a/src/ScriptEngine.HostedScript/Library/ProcessContext.cs +++ b/src/ScriptEngine.HostedScript/Library/ProcessContext.cs @@ -38,6 +38,8 @@ public ProcessContext(System.Diagnostics.Process p):this(p, ValueFactory.Create( { } + private bool IsOutputRedirected => _p.StartInfo.RedirectStandardOutput && _p.StartInfo.RedirectStandardError; + /// /// Устанавливает кодировку в которой будут считываться стандартные потоки вывода и ошибок. /// @@ -59,13 +61,6 @@ public StdTextReadStream StdOut { get { - if (_stdOutContext == null) - { - var stream = new ProcessOutputWrapper(_p, ProcessOutputWrapper.OutputVariant.Stdout); - stream.StartReading(); - - _stdOutContext = new StdTextReadStream(stream); - } return _stdOutContext; } } @@ -79,13 +74,6 @@ public StdTextReadStream StdErr { get { - if (_stdErrContext == null) - { - var stream = new ProcessOutputWrapper(_p, ProcessOutputWrapper.OutputVariant.Stderr); - stream.StartReading(); - - _stdErrContext = new StdTextReadStream(stream); - } return _stdErrContext; } } @@ -112,6 +100,19 @@ public StdTextWriteStream StdIn public void Start() { _p.Start(); + + if (IsOutputRedirected) + { + var stream = new ProcessOutputWrapper(_p, ProcessOutputWrapper.OutputVariant.Stdout); + stream.StartReading(); + _stdOutContext = new StdTextReadStream(stream); + + stream = new ProcessOutputWrapper(_p, ProcessOutputWrapper.OutputVariant.Stderr); + stream.StartReading(); + + _stdErrContext = new StdTextReadStream(stream); + + } } /// @@ -159,14 +160,22 @@ public int ExitCode return _p.ExitCode; } } - + /// /// Приостановить выполнение скрипта и ожидать завершения процесса. /// + /// Число. Таймаут в миллисекундах. + /// Булево. Ложь, если таймаут истек. [ContextMethod("ОжидатьЗавершения", "WaitForExit")] - public void WaitForExit() + public bool WaitForExit(IValue timeout = null) { - _p.WaitForExit(); + if (timeout == null) + { + _p.WaitForExit(); + return true; + } + + return _p.WaitForExit((int) timeout.AsNumber()); } /// @@ -210,7 +219,7 @@ public void Dispose() _p.Dispose(); } - public static ProcessContext Create(string cmdLine, string currentDir = null, bool redirectOutput = false, bool redirectInput = false, IValue encoding = null) + public static ProcessContext Create(string cmdLine, string currentDir = null, bool redirectOutput = false, bool redirectInput = false, IValue encoding = null, MapImpl env = null) { var sInfo = PrepareProcessStartupInfo(cmdLine, currentDir); sInfo.UseShellExecute = false; @@ -231,6 +240,14 @@ public static ProcessContext Create(string cmdLine, string currentDir = null, bo sInfo.StandardErrorEncoding = enc; } + if (env != null) + { + foreach (var kv in env) + { + sInfo.EnvironmentVariables[kv.Key.AsString()] = kv.Value.AsString(); + } + } + var p = new System.Diagnostics.Process(); p.StartInfo = sInfo; diff --git a/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs b/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs index ceacf1216..722354d83 100644 --- a/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs +++ b/src/ScriptEngine.HostedScript/Library/ProcessOutputWrapper.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using System.IO; using System.Linq; @@ -70,56 +76,39 @@ private void StopReading() private void StreamDataReceived(object sender, sys.DataReceivedEventArgs e) { - try + if (e.Data != null) { - if (e.Data != null) + lock(_buffer) { - _locker.EnterWriteLock(); if (_buffer.Length != 0) _buffer.Append(System.Environment.NewLine); _buffer.Append(e.Data); } } - finally - { - if(_locker.IsWriteLockHeld) // При else бросит правильное исключение, из-за которого не захватил блокировку - _locker.ExitWriteLock(); - } } public override int Peek() { - try + lock (_buffer) { - EnterReadLock(); if (_bufferIndex >= _buffer.Length) return -1; // no data - return _buffer[_bufferIndex]; - } - finally - { - if (_locker.IsReadLockHeld) // При else бросит правильное исключение, из-за которого не захватил блокировку - _locker.ExitReadLock(); + return _buffer[_bufferIndex]; } - } public override int Read() { - try + lock (_buffer) { - EnterReadLock(); return ReadInternal(); } - finally - { - if (_locker.IsReadLockHeld) - _locker.ExitReadLock(); - } } + // неблокирующий доступ к буферу. + // должна вызываться ТОЛЬКО внутри вышестоящего блока lock. private int ReadInternal() { if (_bufferIndex < _buffer.Length) @@ -139,33 +128,27 @@ public override int Read(char[] destBuffer, int index, int count) if (destBuffer.Length - index < count) throw new ArgumentException("Invalid offset"); - try + + int n = 0; + lock (_buffer) { - EnterReadLock(); - int n = 0; do { int ch = ReadInternal(); if (ch == -1) break; - destBuffer[index + n++] = (char) ch; - } while (n < count); - - return n; - } - finally - { - if (_locker.IsReadLockHeld) - _locker.ExitReadLock(); + destBuffer[index + n++] = (char)ch; + } while (n < count); } + + return n; } public override string ReadLine() { - try + var sb = new StringBuilder(); + lock (_buffer) { - EnterReadLock(); - var sb = new StringBuilder(); while (true) { int ch = ReadInternal(); @@ -176,30 +159,21 @@ public override string ReadLine() return sb.ToString(); } sb.Append((char)ch); - } - if (sb.Length > 0) return sb.ToString(); - return null; - } - finally - { - if (_locker.IsReadLockHeld) - _locker.ExitReadLock(); + } } + if (sb.Length > 0) + return sb.ToString(); + + return null; } public override string ReadToEnd() { - try + lock (_buffer) { - EnterReadLock(); string data = base.ReadToEnd(); ResetBuffer(); - return data; - } - finally - { - if (_locker.IsReadLockHeld) - _locker.ExitReadLock(); + return data; } } @@ -209,16 +183,6 @@ private void ResetBuffer() _bufferIndex = 0; } - private void EnterReadLock() - { - if (_process.HasExited) - { - _process.WaitForExit(); // ожидание закрытия потоков - } - - _locker.EnterReadLock(); - } - protected override void Dispose(bool disposing) { if (disposing) diff --git a/src/ScriptEngine.HostedScript/Library/RandomNumberGenerator.cs b/src/ScriptEngine.HostedScript/Library/RandomNumberGenerator.cs index 662da1235..0372a66f7 100644 --- a/src/ScriptEngine.HostedScript/Library/RandomNumberGenerator.cs +++ b/src/ScriptEngine.HostedScript/Library/RandomNumberGenerator.cs @@ -11,7 +11,7 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library { [ContextClass("ГенераторСлучайныхЧисел", "RandomNumberGenerator")] - class RandomNumberGenerator : AutoContext + public class RandomNumberGenerator : AutoContext { private readonly Random _random; diff --git a/src/ScriptEngine.HostedScript/Library/Reflector.cs b/src/ScriptEngine.HostedScript/Library/Reflector.cs index 5dbc2e689..5884534ff 100644 --- a/src/ScriptEngine.HostedScript/Library/Reflector.cs +++ b/src/ScriptEngine.HostedScript/Library/Reflector.cs @@ -110,9 +110,9 @@ public ValueTable.ValueTable GetMethodsTable(IRuntimeContextInstance target) { ValueTable.ValueTable Result = new ValueTable.ValueTable(); - var NameColumn = Result.Columns.Add("Имя", ValueFactory.Create(""), "Имя"); // TODO: Доработать после увеличения предела количества параметров - var CountColumn = Result.Columns.Add("КоличествоПараметров", ValueFactory.Create(""), "Количество параметров"); // TODO: Доработать после увеличения предела количества параметров - var IsFunctionColumn = Result.Columns.Add("ЭтоФункция", ValueFactory.Create(""), "Это функция"); // TODO: Доработать после увеличения предела количества параметров + var NameColumn = Result.Columns.Add("Имя", TypeDescription.StringType(), "Имя"); + var CountColumn = Result.Columns.Add("КоличествоПараметров", TypeDescription.IntegerType(), "Количество параметров"); + var IsFunctionColumn = Result.Columns.Add("ЭтоФункция", TypeDescription.BooleanType(), "Это функция"); foreach(var methInfo in target.GetMethods()) { @@ -123,7 +123,32 @@ public ValueTable.ValueTable GetMethodsTable(IRuntimeContextInstance target) } return Result; - } + } + + /// + /// Получает таблицу свойств для переданного объекта.. + /// + /// Объект, из которого получаем таблицу свойств. + /// Таблица значений с 1 колонкой - Имя + [ContextMethod("ПолучитьТаблицуСвойств", "GetPropertiesTable")] + public ValueTable.ValueTable GetPropertiesTable(IRuntimeContextInstance target) + { + ValueTable.ValueTable Result = new ValueTable.ValueTable(); + + var NameColumn = Result.Columns.Add("Имя", TypeDescription.StringType(), "Имя"); + + var SystemVarNames = new string[] { "этотобъект", "thisobject" }; + + foreach (var propInfo in target.GetProperties()) + { + if (SystemVarNames.Contains(propInfo.Identifier.ToLower())) continue; + + ValueTableRow new_row = Result.Add(); + new_row.Set(NameColumn, ValueFactory.Create(propInfo.Identifier)); + } + + return Result; + } [ScriptConstructor] public static IRuntimeContextInstance CreateNew() diff --git a/src/ScriptEngine.HostedScript/Library/Regex/MatchCollectionImpl.cs b/src/ScriptEngine.HostedScript/Library/Regex/MatchCollectionImpl.cs index d2e84a768..af219d975 100644 --- a/src/ScriptEngine.HostedScript/Library/Regex/MatchCollectionImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/Regex/MatchCollectionImpl.cs @@ -14,7 +14,7 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library.Regex { [ContextClass("КоллекцияСовпаденийРегулярногоВыражения", "RegExMatchCollection")] - class MatchCollection : AutoContext, ICollectionContext, IEnumerable + public class MatchCollection : AutoContext, ICollectionContext, IEnumerable { private readonly RegExp.MatchCollection _matches; @@ -70,7 +70,7 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() } [ContextClass("КоллекцияГруппРегулярногоВыражения", "RegExGroupCollection")] - class GroupCollection : AutoContext, ICollectionContext, IEnumerable + public class GroupCollection : AutoContext, ICollectionContext, IEnumerable { private readonly RegExp.GroupCollection _groups; diff --git a/src/ScriptEngine.HostedScript/Library/Regex/MatchImpl.cs b/src/ScriptEngine.HostedScript/Library/Regex/MatchImpl.cs index 635332c9a..110b5eff5 100644 --- a/src/ScriptEngine.HostedScript/Library/Regex/MatchImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/Regex/MatchImpl.cs @@ -11,7 +11,7 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library.Regex { [ContextClass("СовпадениеРегулярногоВыражения", "RegExMatch")] - class MatchImpl : AutoContext + public class MatchImpl : AutoContext { private readonly RegExp.Match _match; @@ -58,7 +58,7 @@ public GroupCollection Groups } [ContextClass("ГруппаРегулярногоВыражения", "RegExGroup")] - class GroupImpl : AutoContext + public class GroupImpl : AutoContext { private readonly RegExp.Group _group; diff --git a/src/ScriptEngine.HostedScript/Library/SpecialFolderEnum.cs b/src/ScriptEngine.HostedScript/Library/SpecialFolderEnum.cs new file mode 100644 index 000000000..3f0fe9242 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/SpecialFolderEnum.cs @@ -0,0 +1,52 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + +using ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; + +using sysFolder = System.Environment.SpecialFolder; + +namespace ScriptEngine.HostedScript.Library +{ + /// + /// Системное перечисление для специальных папок. + /// + [SystemEnum("СпециальнаяПапка", "SpecialFolder")] + class SpecialFolderEnum : EnumerationContext + { + private SpecialFolderEnum(TypeDescriptor typeRepresentation, TypeDescriptor valuesType) + : base(typeRepresentation, valuesType) + { + + } + + public static SpecialFolderEnum CreateInstance() + { + SpecialFolderEnum instance; + var type = TypeManager.RegisterType("ПеречислениеСпециальнаяПапка", typeof(SpecialFolderEnum)); + var enumValueType = TypeManager.RegisterType("СпециальнаяПапка", typeof(CLREnumValueWrapper)); + + instance = new SpecialFolderEnum(type, enumValueType); + + instance.AddValue("МоиДокументы", "MyDocuments", new CLREnumValueWrapper(instance, sysFolder.Personal)); + instance.AddValue("ДанныеПриложений", "ApplicationData", new CLREnumValueWrapper(instance, sysFolder.ApplicationData)); + instance.AddValue("ЛокальныйКаталогДанныхПриложений", "LocalApplicationData", new CLREnumValueWrapper(instance, sysFolder.LocalApplicationData)); + instance.AddValue("РабочийСтол", "Desktop", new CLREnumValueWrapper(instance, sysFolder.Desktop)); + instance.AddValue("КаталогРабочийСтол", "DesktopDirectory", new CLREnumValueWrapper(instance, sysFolder.DesktopDirectory)); + instance.AddValue("МояМузыка", "MyMusic", new CLREnumValueWrapper(instance, sysFolder.MyMusic)); + instance.AddValue("МоиРисунки", "MyPictures", new CLREnumValueWrapper(instance, sysFolder.MyPictures)); + instance.AddValue("Шаблоны", "Templates", new CLREnumValueWrapper(instance, sysFolder.Templates)); + instance.AddValue("МоиВидеозаписи", "MyVideos", new CLREnumValueWrapper(instance, sysFolder.MyVideos)); + instance.AddValue("ОбщиеШаблоны", "CommonTemplates", new CLREnumValueWrapper(instance, sysFolder.CommonTemplates)); + instance.AddValue("ПрофильПользователя", "UserProfile", new CLREnumValueWrapper(instance, sysFolder.UserProfile)); + instance.AddValue("ОбщийКаталогДанныхПриложения", "CommonApplicationData", new CLREnumValueWrapper(instance, sysFolder.CommonApplicationData)); + + return instance; + } + } + +} diff --git a/src/ScriptEngine.HostedScript/Library/StdTextReadStream.cs b/src/ScriptEngine.HostedScript/Library/StdTextReadStream.cs index a732efee5..e4229f697 100644 --- a/src/ScriptEngine.HostedScript/Library/StdTextReadStream.cs +++ b/src/ScriptEngine.HostedScript/Library/StdTextReadStream.cs @@ -49,9 +49,14 @@ public bool HasData /// /// Строка [ContextMethod("Прочитать", "Read")] - public string Read() + public IValue Read() { - return _reader.ReadToEnd(); + var readResult = _reader.ReadToEnd(); + + if(readResult == String.Empty) + return ValueFactory.Create(); + + return ValueFactory.Create(readResult); } /// diff --git a/src/ScriptEngine.HostedScript/Library/StringOperations.cs b/src/ScriptEngine.HostedScript/Library/StringOperations.cs index 7f43c1368..ca2f18d10 100644 --- a/src/ScriptEngine.HostedScript/Library/StringOperations.cs +++ b/src/ScriptEngine.HostedScript/Library/StringOperations.cs @@ -97,7 +97,6 @@ public bool StrEndsWith(string inputString, string searchString) [ContextMethod("СтрРазделить", "StrSplit")] public ArrayImpl StrSplit(string inputString, string stringDelimiter, bool includeEmpty = true) { - ArrayImpl arrResult = new ArrayImpl(); string[] arrParsed; if(!string.IsNullOrEmpty(inputString)) { @@ -113,8 +112,7 @@ public ArrayImpl StrSplit(string inputString, string stringDelimiter, bool inclu { arrParsed = new string[] { string.Empty }; } - arrResult = new ArrayImpl(arrParsed.Select(x => ValueFactory.Create(x))); - return arrResult; + return new ArrayImpl(arrParsed.Select(x => ValueFactory.Create(x))); } /// diff --git a/src/ScriptEngine.HostedScript/Library/SymbolsContext.cs b/src/ScriptEngine.HostedScript/Library/SymbolsContext.cs new file mode 100644 index 000000000..936fa48d9 --- /dev/null +++ b/src/ScriptEngine.HostedScript/Library/SymbolsContext.cs @@ -0,0 +1,94 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine; +using ScriptEngine.Machine.Contexts; + +namespace ScriptEngine.HostedScript.Library +{ + [ContextClass("Символы", "Chars")] + public sealed class SymbolsContext : AutoContext + { + /// + /// Символ перевода строки. + /// + /// Символ перевода строки. + [ContextProperty("ПС")] + public string LF + { + get + { + return "\n"; + } + } + + /// + /// Символ возврата каретки. + /// + /// Символ возврата каретки. + [ContextProperty("ВК")] + public string CR + { + get + { + return "\r"; + } + } + + /// + /// Символ вертикальной табуляции. + /// + /// Символ вертикальной табуляции. + [ContextProperty("ВТаб")] + public string VTab + { + get + { + return "\v"; + } + } + + /// + /// Символ табуляции. + /// + /// Символ горизонтальной табуляции. + [ContextProperty("Таб")] + public string Tab + { + get + { + return "\t"; + } + } + + /// + /// Символ промотки. + /// + /// Символ промотки. + [ContextProperty("ПФ")] + public string FF + { + get + { + return "\f"; + } + } + + /// + /// Символ неразрывного пробела. + /// + /// Символ неразрывного пробела. + [ContextProperty("НПП")] + public string Nbsp + { + get + { + return "\u00A0"; + } + } + + } +} diff --git a/src/ScriptEngine.HostedScript/Library/SymbolsEnum.cs b/src/ScriptEngine.HostedScript/Library/SymbolsEnum.cs deleted file mode 100644 index 0363a12fa..000000000 --- a/src/ScriptEngine.HostedScript/Library/SymbolsEnum.cs +++ /dev/null @@ -1,83 +0,0 @@ -/*---------------------------------------------------------- -This Source Code Form is subject to the terms of the -Mozilla Public License, v.2.0. If a copy of the MPL -was not distributed with this file, You can obtain one -at http://mozilla.org/MPL/2.0/. -----------------------------------------------------------*/ -using ScriptEngine.Machine; -using ScriptEngine.Machine.Contexts; - -namespace ScriptEngine.HostedScript.Library -{ - - [SystemEnum("Символы", "Chars")] - public class SymbolsEnum : EnumerationContext - { - private SymbolsEnum(TypeDescriptor typeRepresentation, TypeDescriptor valuesType) - :base(typeRepresentation, valuesType) - { - - } - - class SymbolsEnumValue : EnumerationValue - { - readonly string _val; - - public SymbolsEnumValue(EnumerationContext owner, string val) - : base(owner) - { - _val = val; - } - - public override string AsString() - { - return _val; - } - - public override DataType DataType - { - get - { - return DataType.String; - } - } - - public override TypeDescriptor SystemType - { - get - { - return TypeDescriptor.FromDataType(DataType); - } - } - - public override int CompareTo(IValue other) - { - return _val.CompareTo(other.AsString()); - } - - public override bool Equals(IValue other) - { - return _val == other.AsString(); - } - } - - public static SymbolsEnum CreateInstance() - { - - var type = TypeManager.RegisterType("Символы", typeof(SymbolsEnum)); - var stringType = TypeDescriptor.FromDataType(DataType.String); - var instance = new SymbolsEnum(type, stringType); - - instance.AddValue("ПС", "LF", new SymbolsEnumValue(instance, "\n")); - instance.AddValue("ВК", "CR", new SymbolsEnumValue(instance, "\r")); - instance.AddValue("ВТаб", "VTab", new SymbolsEnumValue(instance, "\v")); - instance.AddValue("Таб", "Tab", new SymbolsEnumValue(instance, "\t")); - instance.AddValue("ПФ", "FF", new SymbolsEnumValue(instance, "\f")); - instance.AddValue("НПП", "NBSp", new SymbolsEnumValue(instance, "\u00A0")); - - return instance; - } - - } - -} diff --git a/src/ScriptEngine.HostedScript/Library/SystemEnvironmentContext.cs b/src/ScriptEngine.HostedScript/Library/SystemEnvironmentContext.cs index 76f317ff7..a2adc079f 100644 --- a/src/ScriptEngine.HostedScript/Library/SystemEnvironmentContext.cs +++ b/src/ScriptEngine.HostedScript/Library/SystemEnvironmentContext.cs @@ -52,6 +52,117 @@ public string Version } } + /// + /// Имя пользователя ОС с учетом домена + /// Формат строки: \\ИмяДомена\ИмяПользователя. + /// + [ContextProperty("ПользовательОС", "OSUser")] + public string OSUser + { + get + { + string DomainName = System.Environment.UserDomainName; + + if (DomainName != "") + { + return @"\\" + DomainName + @"\" + System.Environment.UserName; + } + + return System.Environment.UserName; + } + } + + /// + /// Определяет, является ли текущая операционная система 64-разрядной. + /// + [ContextProperty("Это64БитнаяОперационнаяСистема")] + public bool Is64BitOperatingSystem + { + get { return System.Environment.Is64BitOperatingSystem; } + } + + /// + /// Возвращает число процессоров. + /// 32-битовое целое число со знаком, которое возвращает количество процессоров на текущем компьютере. + /// Значение по умолчанию отсутствует. Если текущий компьютер содержит несколько групп процессоров, + /// данное свойство возвращает число логических процессоров, доступных для использования средой CLR + /// + [ContextProperty("КоличествоПроцессоров")] + public int ProcessorCount + { + get { return System.Environment.ProcessorCount; } + } + + /// + /// Возвращает количество байтов на странице памяти операционной системы + /// + [ContextProperty("РазмерСистемнойСтраницы")] + public int SystemPageSize + { + get { return System.Environment.SystemPageSize; } + } + + /// + /// Возвращает время, истекшее с момента загрузки системы (в миллисекундах). + /// + [ContextProperty("ВремяРаботыСМоментаЗагрузки")] + public long TickCount + { + get + { + var unsig = (uint)System.Environment.TickCount; + return unsig; + } + } + + /// + /// Возвращает путь для специальной папки. Поддерживаемые значения: + /// + /// * МоиДокументы / MyDocuments + /// * ДанныеПриложений / ApplicationData + /// * ЛокальныйКаталогДанныхПриложений / LocalApplicationData + /// * РабочийСтол / Desktop + /// * КаталогРабочийСтол / DesktopDirectory + /// * МояМузыка / MyMusic + /// * МоиРисунки / MyPictures + /// * Шаблоны / Templates + /// * МоиВидеозаписи / MyVideos + /// * ОбщиеШаблоны / CommonTemplates + /// * ПрофильПользователя / UserProfile + /// * ОбщийКаталогДанныхПриложения / CommonApplicationData + /// + /// Тип: СпециальнаяПапка + /// Строка + [ContextMethod("ПолучитьПутьПапки")] + public string GetFolderPath(IValue folder) + { + var typedValue = folder as CLREnumValueWrapper; + if (typedValue == null) + throw RuntimeException.InvalidArgumentType(); + + return System.Environment.GetFolderPath(typedValue.UnderlyingValue); + + } + + /// + /// Возвращает массив строк, содержащий имена логических дисков текущего компьютера. + /// + [ContextProperty("ИменаЛогическихДисков")] + public FixedArrayImpl GetLogicalDrives + { + get + { + var arr = new ArrayImpl(); + var data = System.Environment.GetLogicalDrives(); + foreach (var itm in data) + { + arr.Add(ValueFactory.Create(itm)); + } + return new FixedArrayImpl(arr); + } + } + + /// /// Возвращает соответствие переменных среды. Ключом является имя переменной, а значением - значение переменной /// @@ -65,6 +176,7 @@ public string Version [ContextMethod("ПеременныеСреды", "EnvironmentVariables")] public IRuntimeContextInstance EnvironmentVariables() { + SystemLogger.Write("WARNING! Deprecated method: 'SystemInfo.EnvironmentVariables' is deprecated, use 'EnvironmentVariables' from global context"); var varsMap = new MapImpl(); var allVars = System.Environment.GetEnvironmentVariables(); foreach (DictionaryEntry item in allVars) @@ -86,6 +198,7 @@ public IRuntimeContextInstance EnvironmentVariables() [ContextMethod("УстановитьПеременнуюСреды","SetEnvironmentVariable")] public void SetEnvironmentVariable(string varName, string value) { + SystemLogger.Write("WARNING! Deprecated method: 'SystemInfo.SetEnvironmentVariable' is deprecated, use 'SetEnvironmentVariable' from global context"); System.Environment.SetEnvironmentVariable(varName, value); } @@ -97,6 +210,7 @@ public void SetEnvironmentVariable(string varName, string value) [ContextMethod("ПолучитьПеременнуюСреды", "GetEnvironmentVariable")] public IValue GetEnvironmentVariable(string varName) { + SystemLogger.Write("WARNING! Deprecated method: 'SystemInfo.GetEnvironmentVariable' is deprecated, use 'GetEnvironmentVariable' from global context"); string value = System.Environment.GetEnvironmentVariable(varName); if (value == null) return ValueFactory.Create(); diff --git a/src/ScriptEngine.HostedScript/Library/SystemGlobalContext.cs b/src/ScriptEngine.HostedScript/Library/SystemGlobalContext.cs index 226b1431f..5f28f3b66 100644 --- a/src/ScriptEngine.HostedScript/Library/SystemGlobalContext.cs +++ b/src/ScriptEngine.HostedScript/Library/SystemGlobalContext.cs @@ -7,7 +7,11 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.Linq; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.ComTypes; using System.Text; +using System.Threading; + using ScriptEngine.Environment; using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; @@ -18,21 +22,26 @@ namespace ScriptEngine.HostedScript.Library /// Глобальный контекст. Представляет глобально доступные свойства и методы. /// [GlobalContext(Category="Процедуры и функции взаимодействия с системой", ManualRegistration=true)] - class SystemGlobalContext : IRuntimeContextInstance, IAttachableContext + public class SystemGlobalContext : IRuntimeContextInstance, IAttachableContext { private IVariable[] _state; - private CommandLineArguments _args; + private FixedArrayImpl _args; + private SymbolsContext _symbols; private readonly DynamicPropertiesHolder _propHolder = new DynamicPropertiesHolder(); private readonly List> _properties = new List>(); + private readonly SystemEnvironmentContext _systemEnvironmentContext; public SystemGlobalContext() { RegisterProperty("АргументыКоманднойСтроки", ()=>(IValue)CommandLineArguments); - RegisterProperty("CommandLineArguments", () => (IValue)CommandLineArguments); - - FileStreams = new FileStreamsManager(); + RegisterProperty("CommandLineArguments", () => (IValue)CommandLineArguments); + + FileStreams = new FileStreamsManager(); RegisterProperty("ФайловыеПотоки", () => FileStreams); RegisterProperty("FileStreams", () => FileStreams); + + RegisterProperty("Символы", () => (IValue)Chars); + RegisterProperty("Chars", () => (IValue)Chars); } private void RegisterProperty(string name, Func getter) @@ -59,19 +68,19 @@ private void InitContextVariables() } public IHostApplication ApplicationHost { get; set; } - public ICodeSource CodeSource { get; set; } - - - /// - /// Менеджер файловых потоков. - /// + public ICodeSource CodeSource { get; set; } + + + /// + /// Менеджер файловых потоков. + /// [ContextProperty("ФайловыеПотоки","FileStreams")] public FileStreamsManager FileStreams { get; } /// /// Выдает сообщение в консоль. /// - /// Выдаваемое сообщение. + /// Выдаваемое сообщение. /// Статус сообщения. [ContextMethod("Сообщить", "Message")] public void Echo(string message, MessageStatusEnum status = MessageStatusEnum.Ordinary) @@ -84,10 +93,9 @@ public void Echo(string message, MessageStatusEnum status = MessageStatusEnum.Or /// Подключенный сценарий выступает, как самостоятельный класс, создаваемый оператором Новый /// /// Путь к подключаемому сценарию - /// Имя типа, которое будет иметь новый класс. Экземпляры класса создаются оператором Новый. + /// Имя типа, которое будет иметь новый класс. Экземпляры класса создаются оператором Новый. /// ПодключитьСценарий("C:\file.os", "МойОбъект"); /// А = Новый МойОбъект(); - /// [ContextMethod("ПодключитьСценарий", "AttachScript")] public void AttachScript(string path, string typeName) { @@ -117,8 +125,7 @@ public IRuntimeContextInstance LoadScript(string path, StructureImpl externalCon foreach (var item in externalContext) { - var kv = item as KeyAndValueImpl; - extData.Add(kv.Key.AsString(), kv.Value); + extData.Add(item.Key.AsString(), item.Value); } return EngineInstance.AttachedScriptsFactory.LoadFromPath(compiler, path, extData); @@ -130,11 +137,11 @@ public IRuntimeContextInstance LoadScript(string path, StructureImpl externalCon /// Подключает внешнюю сборку среды .NET (*.dll) и регистрирует классы 1Script, объявленные в этой сборке. /// Публичные классы, отмеченные в dll атрибутом ContextClass, будут импортированы аналогично встроенным классам 1Script. /// Загружаемая сборка должна ссылаться на сборку ScriptEngine.dll + /// /// /// ПодключитьВнешнююКомпоненту("C:\MyAssembly.dll"); /// КлассИзКомпоненты = Новый КлассИзКомпоненты(); // тип объявлен внутри компоненты /// - /// /// Путь к внешней компоненте [ContextMethod("ПодключитьВнешнююКомпоненту", "AttachAddIn")] public void AttachAddIn(string dllPath) @@ -248,14 +255,15 @@ public IRuntimeContextInstance CommandLineArguments { if (_args == null) { - if (ApplicationHost == null) - { - _args = Library.CommandLineArguments.Empty; - } - else + var argsArray = new ArrayImpl(); + if (ApplicationHost != null) { - _args = new CommandLineArguments(ApplicationHost.GetCommandLineArguments()); + foreach (var arg in ApplicationHost.GetCommandLineArguments()) + { + argsArray.Add(ValueFactory.Create(arg)); + } } + _args = new FixedArrayImpl(argsArray); } return _args; @@ -263,6 +271,24 @@ public IRuntimeContextInstance CommandLineArguments } + /// + /// Содержит набор системных символов. + /// + /// Набор системных символов. + [ContextProperty("Символы")] + public IRuntimeContextInstance Chars + { + get + { + if (_symbols == null) + { + _symbols = new SymbolsContext(); + } + + return _symbols; + } + } + /// /// Запуск приложения в операционной системе /// @@ -297,9 +323,9 @@ public void RunApp(string cmdLine, string currentDir = null, bool wait = false, /// Перехватывать стандартный поток stdin /// Кодировка стандартных потоков вывода и ошибок [ContextMethod("СоздатьПроцесс", "CreateProcess")] - public ProcessContext CreateProcess(string cmdLine, string currentDir = null, bool redirectOutput = false, bool redirectInput = false, IValue encoding = null) + public ProcessContext CreateProcess(string cmdLine, string currentDir = null, bool redirectOutput = false, bool redirectInput = false, IValue encoding = null, MapImpl env = null) { - return ProcessContext.Create(cmdLine, currentDir, redirectOutput, redirectInput, encoding); + return ProcessContext.Create(cmdLine, currentDir, redirectOutput, redirectInput, encoding, env); } /// @@ -478,6 +504,48 @@ public void FillPropertyValues(IRuntimeContextInstance acceptor, IRuntimeContext } + + /// + /// Получает объект класса COM по его имени или пути. Подробнее см. синтакс-помощник от 1С. + /// + /// Путь к библиотеке + /// Имя класса + /// COMОбъект + [ContextMethod("ПолучитьCOMОбъект", "GetCOMObject")] + public IValue GetCOMObject(string pathName = null, string className = null) + { + var comObject = GetCOMObjectInternal(pathName, className); + + return COMWrapperContext.Create(comObject); + } + + /// + /// Ported from Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + /// By JetBrains dotPeek decompiler + /// + private object GetCOMObjectInternal(string pathName = null, string className = null) + { + if (String.IsNullOrEmpty(className)) + { + return Marshal.BindToMoniker(pathName); + } + else if (pathName == null) + { + return Marshal.GetActiveObject(className); + } + else if (pathName.Length == 0) + { + return Activator.CreateInstance(System.Type.GetTypeFromProgID(className)); + } + else + { + var persistFile = (IPersistFile)Marshal.GetActiveObject(className); + persistFile.Load(pathName, 0); + + return (object)persistFile; + } + } + #region IAttachableContext Members public void OnAttach(MachineInstance machine, @@ -598,7 +666,6 @@ static SystemGlobalContext() { _methods = new ContextMethodsMapper(); } - - + } } diff --git a/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescription.cs b/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescription.cs index a8f15d34a..24f17b010 100644 --- a/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescription.cs +++ b/src/ScriptEngine.HostedScript/Library/TypeDescription/TypeDescription.cs @@ -16,13 +16,16 @@ public class TypeDescription : AutoContext { private readonly List _types = new List(); - public TypeDescription(IEnumerable types, + public TypeDescription(IEnumerable types = null, NumberQualifiers numberQualifiers = null, StringQualifiers stringQualifiers = null, DateQualifiers dateQualifiers = null, BinaryDataQualifiers binaryDataQualifiers = null) { - _types.AddRange(types); + if (types != null) + { + _types.AddRange(types); + } NumberQualifiers = numberQualifiers ?? new NumberQualifiers(); StringQualifiers = stringQualifiers ?? new StringQualifiers(); DateQualifiers = dateQualifiers ?? new DateQualifiers(); @@ -85,7 +88,7 @@ public IValue AdjustValue(IValue value = null) if (_types.Count == 0) { - return value; + return value ?? ValueFactory.Create(); } TypeTypeValue typeToCast = null; @@ -148,6 +151,40 @@ private static IList ConstructTypeList(IValue types) return _types; } + static TypeTypeValue TypeNumber() + { + return new TypeTypeValue(TypeManager.GetTypeById((int)DataType.Number)); + } + + static TypeTypeValue TypeBoolean() + { + return new TypeTypeValue(TypeManager.GetTypeById((int)DataType.Boolean)); + } + + static TypeTypeValue TypeString() + { + return new TypeTypeValue(TypeManager.GetTypeById((int)DataType.String)); + } + + public static TypeDescription StringType(int length = 0, + AllowedLengthEnum allowedLength = AllowedLengthEnum.Variable) + { + var stringQualifier = new StringQualifiers(length, allowedLength); + return new TypeDescription(new TypeTypeValue[] { TypeString() }, null, stringQualifier); + } + + public static TypeDescription IntegerType(int length = 10, + AllowedSignEnum allowedSign = AllowedSignEnum.Any) + { + var numberQualifier = new NumberQualifiers(length, 0, allowedSign); + return new TypeDescription(new TypeTypeValue[] { TypeNumber() }, numberQualifier); + } + + public static TypeDescription BooleanType() + { + return new TypeDescription(new TypeTypeValue[] { TypeBoolean() }); + } + [ScriptConstructor] public static IRuntimeContextInstance Constructor( IValue source = null, diff --git a/src/ScriptEngine.HostedScript/Library/ValueList/ValueListImpl.cs b/src/ScriptEngine.HostedScript/Library/ValueList/ValueListImpl.cs index a85b00f22..4160dfb25 100644 --- a/src/ScriptEngine.HostedScript/Library/ValueList/ValueListImpl.cs +++ b/src/ScriptEngine.HostedScript/Library/ValueList/ValueListImpl.cs @@ -1,4 +1,10 @@ -using ScriptEngine.Machine; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; using System; using System.Collections.Generic; diff --git a/src/ScriptEngine.HostedScript/Library/ValueList/ValueListItem.cs b/src/ScriptEngine.HostedScript/Library/ValueList/ValueListItem.cs index c50e81dcc..3f1a85f78 100644 --- a/src/ScriptEngine.HostedScript/Library/ValueList/ValueListItem.cs +++ b/src/ScriptEngine.HostedScript/Library/ValueList/ValueListItem.cs @@ -1,4 +1,10 @@ -using ScriptEngine.Machine; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using ScriptEngine.Machine; using ScriptEngine.Machine.Contexts; using System; using System.Collections.Generic; diff --git a/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTable.cs b/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTable.cs index 1af69a63d..75a794444 100644 --- a/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTable.cs +++ b/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTable.cs @@ -13,6 +13,10 @@ This Source Code Form is subject to the terms of the namespace ScriptEngine.HostedScript.Library.ValueTable { + /// + /// Объект для работы с данными в табличном виде. + /// Представляет из себя коллекцию строк с заранее заданной структурой. + /// [ContextClass("ТаблицаЗначений", "ValueTable")] public class ValueTable : AutoContext, ICollectionContext, IEnumerable { @@ -24,24 +28,40 @@ public ValueTable() { } + /// + /// Коллекция колонок + /// + /// КоллекцияКолонокТаблицыЗначений [ContextProperty("Колонки", "Columns")] public ValueTableColumnCollection Columns { get { return _columns; } } + /// + /// Коллекция индексов + /// + /// ИндексыКоллекции [ContextProperty("Индексы", "Indexes")] public CollectionIndexes Indexes { get { return _indexes; } } + /// + /// Количество строк в Таблице значений + /// + /// Число [ContextMethod("Количество", "Count")] public int Count() { return _rows.Count(); } + /// + /// Добавляет строку в конец Таблицы значений + /// + /// СтрокаТаблицыЗначений [ContextMethod("Добавить", "Add")] public ValueTableRow Add() { @@ -50,7 +70,12 @@ public ValueTableRow Add() return row; } - [ContextMethod("ВставитЬ", "Insert")] + /// + /// Вставляет строку в указанную позицию + /// + /// Число - Индекс позиции куда будет произведена вставка + /// СтрокаТаблицыЗначений + [ContextMethod("Вставить", "Insert")] public ValueTableRow Insert(int index) { ValueTableRow row = new ValueTableRow(this); @@ -58,6 +83,13 @@ public ValueTableRow Insert(int index) return row; } + /// + /// Удаляет строку + /// + /// + /// СтрокаТаблицыЗначений - Удаляемая строка + /// Число - Индекс удаляемой строки + /// [ContextMethod("Удалить", "Delete")] public void Delete(IValue Row) { @@ -76,10 +108,19 @@ public void Delete(IValue Row) _rows.RemoveAt(index); } + /// + /// Загружает значения в колонку + /// + /// Массив - Значения для загрузки в колонку + /// + /// Строка - Имя колонки для загрузки + /// Число - Индекс колонки для загрузки + /// КолонкаТаблицыЗначений - Колонка для загрузки + /// [ContextMethod("ЗагрузитьКолонку", "LoadColumn")] public void LoadColumn(IValue Values, IValue ColumnIndex) { - ValueTableColumn Column = Columns.GetColumnByIIndex(ColumnIndex); + // ValueTableColumn Column = Columns.GetColumnByIIndex(ColumnIndex); var row_iterator = _rows.GetEnumerator(); var array_iterator = (Values as ArrayImpl).GetEnumerator(); @@ -89,6 +130,15 @@ public void LoadColumn(IValue Values, IValue ColumnIndex) } } + /// + /// Выгружает значения колонки в новый массив + /// + /// + /// Строка - Имя колонки для выгрузки + /// Число - Индекс колонки для выгрузки + /// КолонкаТаблицыЗначений - Колонка для выгрузки + /// + /// Массив [ContextMethod("ВыгрузитьКолонку", "UnloadColumn")] public ArrayImpl UnloadColumn(IValue Column) { @@ -133,6 +183,11 @@ private List GetProcessingColumnList(string ColumnNames, bool return processing_list; } + /// + /// Заполнить колонку/колонки указанным значением + /// + /// Произвольный - Устанавливаемое значение + /// Строка - Список имен колонок для установки значения (разделены запятыми) [ContextMethod("ЗаполнитьЗначения", "FillValues")] public void FillValues(IValue Value, string ColumnNames = null) { @@ -146,6 +201,11 @@ public void FillValues(IValue Value, string ColumnNames = null) } } + /// + /// Получить индекс указанной строки + /// + /// СтрокаТаблицыЗначений - Строка таблицы значений, для которой необходимо определить индекс + /// Число - Индекс в коллекции, если не найдено возвращает -1 [ContextMethod("Индекс", "IndexOf")] public int IndexOf(IValue Row) { @@ -157,6 +217,15 @@ public int IndexOf(IValue Row) return -1; } + /// + /// Сумма значений всех строк указанной колонки + /// + /// + /// Строка - Имя колонки для суммирования + /// Число - Индекс колонки для суммирования + /// КолонкаТаблицыЗначений - Колонка для суммирования + /// + /// Число [ContextMethod("Итог", "Total")] public IValue Total(IValue ColumnIndex) { @@ -180,6 +249,13 @@ public IValue Total(IValue ColumnIndex) return ValueFactory.Create(); } + /// + /// Осуществляет поиск значения в указанных колонках + /// + /// Произвольный - Искомое значение + /// Строка - Список имен колонок для поиска значения (разделены запятыми). + /// Если параметр не указан - ищет по всем колонкам. По умолчанию: пустая строка + /// СтрокаТаблицыЗначений - если строка найдена, иначе Неопределено [ContextMethod("Найти", "Find")] public IValue Find(IValue Value, string ColumnNames = null) { @@ -211,6 +287,11 @@ private bool CheckFilterCriteria(ValueTableRow Row, StructureImpl Filter) return true; } + /// + /// Поиск строк по условию + /// + /// Структура - Условия поиска. Ключ - имя колонки, значение - искомое значение + /// Массив - Массив ссылок на строки, удовлетворяющих условию поиска [ContextMethod("НайтиСтроки", "FindRows")] public ArrayImpl FindRows(IValue Filter) { @@ -230,12 +311,20 @@ public ArrayImpl FindRows(IValue Filter) return Result; } + /// + /// Удаляет все строки. Структура колонок не меняется. + /// [ContextMethod("Очистить", "Clear")] public void Clear() { _rows.Clear(); } + /// + /// Получить строку по индексу + /// + /// Число - Индекс строки + /// СтрокаТаблицыЗначений [ContextMethod("Получить", "Get")] public ValueTableRow Get(int index) { @@ -244,6 +333,12 @@ public ValueTableRow Get(int index) return _rows[index]; } + /// + /// Сворачиваются (группируются) строки по указанным колонкам измерениям, суммируются колонки ресурсов. + /// Колонки не указанные ни в измерениях ни в ресурсах удаляются. + /// + /// Строка - Имена колонок для сворачивания (изменения), разделены запятыми + /// Строка - Имена колонок для суммирования (ресурсы), разделены запятыми [ContextMethod("Свернуть", "GroupBy")] public void GroupBy(string GroupColumnNames, string AggregateColumnNames = null) { @@ -321,7 +416,15 @@ public void GroupBy(string GroupColumnNames, string AggregateColumnNames = null) } } } - + + /// + /// Сдвигает строку на указанное количество позиций. + /// + /// + /// СтрокаТаблицыЗначений - Строка которую сдвигаем + /// Число - Индекс сдвигаемой строки + /// + /// Количество строк, на которое сдвигается строка. Если значение положительное - сдвиг вниз, иначе вверх [ContextMethod("Сдвинуть", "Move")] public void Move(IValue Row, int Offset) { @@ -357,6 +460,11 @@ public void Move(IValue Row, int Offset) } + /// + /// Создает новую таблицу значений с указанными колонками. Данные не копируются. + /// + /// Строка - Имена колонок для копирования, разделены запятыми + /// ТаблицаЗначений [ContextMethod("СкопироватьКолонки", "CopyColumns")] public ValueTable CopyColumns(string ColumnNames = null) { @@ -366,12 +474,23 @@ public ValueTable CopyColumns(string ColumnNames = null) foreach (ValueTableColumn Column in columns) { - Result.Columns.Add(Column.Name, Column.ValueType, Column.Title); // TODO: Доработать после увеличения предела количества параметров + Result.Columns.Add(Column.Name, Column.ValueType, Column.Title, Column.Width); } return Result; } + /// + /// Создает новую таблицу значений с указанными строками и колонками. Если передан отбор - копирует строки удовлетворяющие отбору. + /// Если не указаны строки - будут скопированы все строки. Если не указаны колонки - будут скопированы все колонки. + /// Если не указаны оба параметра - будет создана полная копия таблицы значений. + /// + /// + /// Массив - Массив строк для отбора + /// Структура - Параметры отбора. Ключ - Колонка, Значение - Значение отбора + /// + /// Строка - Имена колонок для копирования, разделены запятыми + /// ТаблицаЗначений [ContextMethod("Скопировать", "Copy")] public ValueTable Copy(IValue Rows = null, string ColumnNames = null) { @@ -503,12 +622,25 @@ public int Compare(ValueTableRow x, ValueTableRow y) } } + /// + /// Сортировать строки в таблице значений. Строки сортируются по порядку следования колонок для сортировки, с учетом варианта сортировки. + /// + /// Строка - Имена колонок для сортировки. + /// После имени колонки, через пробел, можно указать направление сортировки: "Убыв" ("Desc") - по убыванию. Возр" ("Asc") - по возрастанию + /// По умолчанию - по возрастанию. + /// + /// СравнениеЗначений - правила сравнения значений при наличии различных типов данных в колонке. [ContextMethod("Сортировать", "Sort")] public void Sort(string columns, IValue comparator = null) { _rows.Sort(new RowComparator(GetSortRules(columns))); } + /// + /// Не поддерживается + /// + /// + /// [ContextMethod("ВыбратьСтроку", "ChooseRow")] public void ChooseRow(string title = null, IValue startRow = null) { diff --git a/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableColumn.cs b/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableColumn.cs index afab2cdeb..1ffe2021d 100644 --- a/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableColumn.cs +++ b/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableColumn.cs @@ -5,21 +5,21 @@ This Source Code Form is subject to the terms of the at http://mozilla.org/MPL/2.0/. ----------------------------------------------------------*/ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; using ScriptEngine.Machine.Contexts; using ScriptEngine.Machine; namespace ScriptEngine.HostedScript.Library.ValueTable { + /// + /// Колонка таблицы значений. + /// [ContextClass("КолонкаТаблицыЗначений", "ValueTableColumn")] public class ValueTableColumn : AutoContext { private string _title; private string _name; - private IValue _valueType; + private TypeDescription _valueType; private int _width; private readonly WeakReference _owner; @@ -27,11 +27,11 @@ public class ValueTableColumn : AutoContext // Порядковый номер колонки не может быть использовать из-за своей изменчивости. private readonly int _id; - public ValueTableColumn(ValueTableColumnCollection Owner, int id, string Name, string Title, IValue Type, int Width) + public ValueTableColumn(ValueTableColumnCollection Owner, int id, string Name, string Title, TypeDescription Type, int Width) { _name = Name; - _title = Title; - _valueType = Type; + _title = Title; + _valueType = Type ?? new TypeDescription(); _width = Width; _owner = new WeakReference(Owner); @@ -44,13 +44,21 @@ public int ID get { return _id; } } + /// + /// Заголовок колонки + /// + /// Строка [ContextProperty("Заголовок", "Title")] public string Title { - get { return _title == null ? _name : _title; } + get { return _title ?? _name; } set { _title = value; } } + /// + /// Имя колонки + /// + /// Строка [ContextProperty("Имя", "Name")] public string Name { @@ -68,17 +76,25 @@ public string Name } } - [ContextProperty("ТипЗначения", "ValueType")] - public IValue ValueType + /// + /// Тип значения колонки + /// + /// ОписаниеТипа + [ContextProperty("ТипЗначения", "ValueType")] + public TypeDescription ValueType { get { return _valueType; } - set { _valueType = value; } // TODO: Проверить тип } + + /// + /// Ширина колонки + /// + /// Число [ContextProperty("Ширина", "Width")] public int Width { get { return _width; } - set { _width = value; } // TOOD: Проверить неотрицательность значения + set { _width = value; } } } } diff --git a/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableColumnCollection.cs b/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableColumnCollection.cs index 1fa2645ca..a3f65a928 100644 --- a/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableColumnCollection.cs +++ b/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableColumnCollection.cs @@ -6,13 +6,14 @@ This Source Code Form is subject to the terms of the ----------------------------------------------------------*/ using System; using System.Collections.Generic; -using System.Linq; -using System.Text; using ScriptEngine.Machine.Contexts; using ScriptEngine.Machine; namespace ScriptEngine.HostedScript.Library.ValueTable { + /// + /// Коллекция колонок таблицы значений + /// [ContextClass("КоллекцияКолонокТаблицыЗначений", "ValueTableColumnCollection")] public class ValueTableColumnCollection : DynamicPropertiesAccessor, ICollectionContext, IEnumerable { @@ -23,48 +24,70 @@ public ValueTableColumnCollection() { } - [ContextMethod("Добавить", "Add")] - public ValueTableColumn Add(string Name, IValue Type = null, string Title = null) - { - if (FindColumnByName(Name) != null) - throw new RuntimeException("Неверное имя колонки " + Name); - - var Width = 0; // затычка - - ValueTableColumn column = new ValueTableColumn(this, ++_internal_counter, Name, Title, Type, Width); - _columns.Add(column); - - return column; - } - - [ContextMethod("Вставить", "Insert")] - public ValueTableColumn Insert(int index, string Name, IValue Type = null) - // TODO: добавить Title и Width после того, как количество обрабатываемых параметров будет увеличено хотя бы до 5 - { - if (FindColumnByName(Name) != null) - throw new RuntimeException("Неверное имя колонки " + Name); - - var Title = Name; // TODO: Затычка - var Width = 0; // TODO: Затычка - - ValueTableColumn column = new ValueTableColumn(this, ++_internal_counter, Name, Title, Type, Width); - _columns.Insert(index, column); - - return column; + /// + /// Добавляет колонку в таблицу значений + /// + /// Строка - Имя колонки + /// ОписаниеТипов - Тип данных колонки + /// Строка - Заголовок колонки + /// КолонкаТаблицыЗначений + [ContextMethod("Добавить", "Add")] + public ValueTableColumn Add(string Name, TypeDescription Type = null, string Title = null, int Width = 0) + { + if (FindColumnByName(Name) != null) + throw new RuntimeException("Неверное имя колонки " + Name); + + var column = new ValueTableColumn(this, ++_internal_counter, Name, Title, Type, Width); + _columns.Add(column); + + return column; + } + + /// + /// Вставить колонку в указанную позицию + /// + /// Число - Индекс расположения колонки + /// Строка - Имя колонки + /// ОписаниеТипов - Тип данных колонки + /// КолонкаТаблицыЗначений + [ContextMethod("Вставить", "Insert")] + public ValueTableColumn Insert(int index, string Name, TypeDescription Type = null, string Title = null, int Width = 0) + { + if (FindColumnByName(Name) != null) + throw new RuntimeException("Неверное имя колонки " + Name); + + ValueTableColumn column = new ValueTableColumn(this, ++_internal_counter, Name, Title, Type, Width); + _columns.Insert(index, column); + + return column; } + /// + /// Индекс указанной колонки + /// + /// КолонкаТаблицыЗначений - Колонка, для которой определяется индекс + /// Число [ContextMethod("Индекс", "IndexOf")] public int IndexOf(ValueTableColumn column) { return _columns.IndexOf(column); } + /// + /// Количество колонок в таблице значений + /// + /// Число [ContextMethod("Количество", "Count")] public int Count() { return _columns.Count; } + /// + /// Поиск колонки по имени + /// + /// Строка - Имя колонки + /// КолонкаТаблицыЗначений - Найденная колонка таблицы значений, иначе Неопределено. [ContextMethod("Найти", "Find")] public IValue Find(string Name) { @@ -74,6 +97,14 @@ public IValue Find(string Name) return Column; } + /// + /// Удалить колонку значений + /// + /// + /// Строка - Имя колонки для удаления + /// Число - Индекс колонки для удаления + /// КолонкаТаблицыЗначений - Колонка для удаления + /// [ContextMethod("Удалить", "Delete")] public void Delete(IValue Column) { @@ -152,7 +183,8 @@ public ValueTableColumn GetColumnByIIndex(IValue index) return Column; } - if (index is ValueTableColumn) { + if (index is ValueTableColumn) + { return index as ValueTableColumn; } @@ -177,8 +209,7 @@ public override void CallAsProcedure(int methodNumber, IValue[] arguments) try { binding(this, arguments); - } - catch (System.Reflection.TargetInvocationException e) + } catch (System.Reflection.TargetInvocationException e) { throw e.InnerException; } @@ -190,8 +221,7 @@ public override void CallAsFunction(int methodNumber, IValue[] arguments, out IV try { retValue = binding(this, arguments); - } - catch (System.Reflection.TargetInvocationException e) + } catch (System.Reflection.TargetInvocationException e) { throw e.InnerException; } diff --git a/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableRow.cs b/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableRow.cs index 352952087..9239381b6 100644 --- a/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableRow.cs +++ b/src/ScriptEngine.HostedScript/Library/ValueTable/ValueTableRow.cs @@ -26,24 +26,35 @@ public ValueTableRow(ValueTable Owner) public int Count() { - var Owner = _owner.Target as ValueTable; - return Owner.Columns.Count(); + var owner = _owner.Target as ValueTable; + return owner.Columns.Count(); } + /// + /// Владелец строки + /// + /// ТаблицаЗначений [ContextMethod("Владелец", "Owner")] public ValueTable Owner() { return _owner.Target as ValueTable; } - private IValue TryValue(ValueTableColumn Column) - { - IValue Value; - if (_data.TryGetValue(Column, out Value)) - return Value; - return ValueFactory.Create(); // TODO: Определять пустое значение для типа колонки - } - + private IValue TryValue(ValueTableColumn Column) + { + IValue Value; + if (_data.TryGetValue(Column, out Value)) + { + return Value; + } + return Column.ValueType.AdjustValue(); + } + + /// + /// Получает значение по индексу + /// + /// Число - Индекс колонки + /// Произвольный - Значение колонки [ContextMethod("Получить", "Get")] public IValue Get(int index) { @@ -62,22 +73,27 @@ public IValue Get(ValueTableColumn C) return TryValue(C); } + /// + /// Установить значение + /// + /// Число - Индекс колонки + /// Произвольный - значение для установки [ContextMethod("Установить", "Set")] public void Set(int index, IValue Value) { var C = Owner().Columns.FindColumnByIndex(index); - _data[C] = Value; + _data[C] = C.ValueType.AdjustValue(Value); } public void Set(IValue index, IValue Value) { var C = Owner().Columns.GetColumnByIIndex(index); - _data[C] = Value; + _data[C] = C.ValueType.AdjustValue(Value); } public void Set(ValueTableColumn Column, IValue Value) { - _data[Column] = Value; + _data[Column] = Column.ValueType.AdjustValue(Value); } public IEnumerator GetEnumerator() @@ -114,11 +130,11 @@ public override IValue GetPropValue(int propNum) return TryValue(C); } - public override void SetPropValue(int propNum, IValue newVal) - { - ValueTableColumn C = Owner().Columns.FindColumnById(propNum); - _data[C] = newVal; - } + public override void SetPropValue(int propNum, IValue newVal) + { + ValueTableColumn C = Owner().Columns.FindColumnById(propNum); + _data[C] = C.ValueType.AdjustValue(newVal); + } private ValueTableColumn GetColumnByIIndex(IValue index) { @@ -131,10 +147,11 @@ public override IValue GetIndexedValue(IValue index) return TryValue(C); } - public override void SetIndexedValue(IValue index, IValue val) - { - _data[GetColumnByIIndex(index)] = val; - } + public override void SetIndexedValue(IValue index, IValue val) + { + var C = GetColumnByIIndex(index); + _data[C] = C.ValueType.AdjustValue(val); + } private static readonly ContextMethodsMapper _methods = new ContextMethodsMapper(); diff --git a/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeColumn.cs b/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeColumn.cs index 00484aca4..42c2225d0 100644 --- a/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeColumn.cs +++ b/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeColumn.cs @@ -21,7 +21,7 @@ public class ValueTreeColumn : AutoContext { private string _title; private string _name; - private IValue _valueType; + private TypeDescription _valueType; private int _width; private readonly ValueTreeColumnCollection _owner; @@ -29,11 +29,11 @@ public class ValueTreeColumn : AutoContext // Порядковый номер колонки не может быть использовать из-за своей изменчивости. private readonly int _id; - public ValueTreeColumn(ValueTreeColumnCollection Owner, int id, string Name, string Title, IValue Type, int Width) + public ValueTreeColumn(ValueTreeColumnCollection Owner, int id, string Name, string Title, TypeDescription Type, int Width) { _name = Name; _title = Title ?? Name; - _valueType = Type; + _valueType = Type ?? new TypeDescription(); _width = Width; _owner = Owner; @@ -60,7 +60,7 @@ public int ID [ContextProperty("Заголовок", "Title")] public string Title { - get { return _title == null ? _name : _title; } + get { return _title ?? _name; } set { _title = value; } } @@ -81,16 +81,15 @@ public string Name } [ContextProperty("ТипЗначения", "ValueType")] - public IValue ValueType + public TypeDescription ValueType { get { return _valueType; } - set { _valueType = value; } // TODO: Проверить тип } [ContextProperty("Ширина", "Width")] public int Width { - get { return Width; } + get { return _width; } set { _width = value; } // TOOD: Проверить неотрицательность значения } diff --git a/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeColumnCollection.cs b/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeColumnCollection.cs index 2622f8927..75f0680bf 100644 --- a/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeColumnCollection.cs +++ b/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeColumnCollection.cs @@ -36,7 +36,7 @@ public ValueTreeColumnCollection() /// Число. Ширина колонки. Необязательный параметр. /// КолонкаДереваЗначений. Добавленная колонка. [ContextMethod("Добавить", "Add")] - public ValueTreeColumn Add(string name, IValue type = null, string title = null, int width = 0) + public ValueTreeColumn Add(string name, TypeDescription type = null, string title = null, int width = 0) { if (FindColumnByName(name) != null) throw new RuntimeException("Неверное имя колонки " + name); @@ -57,7 +57,7 @@ public ValueTreeColumn Add(string name, IValue type = null, string title = null, /// Число. Ширина колонки. Необязательный параметр. /// КолонкаДереваЗначений. Добавленная колонка. [ContextMethod("Вставить", "Insert")] - public ValueTreeColumn Insert(int index, string name, IValue type = null, string title = null, int width = 0) + public ValueTreeColumn Insert(int index, string name, TypeDescription type = null, string title = null, int width = 0) { if (FindColumnByName(name) != null) throw new RuntimeException("Неверное имя колонки " + name); diff --git a/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeRow.cs b/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeRow.cs index f0d3c09a7..d82f000b2 100644 --- a/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeRow.cs +++ b/src/ScriptEngine.HostedScript/Library/ValueTree/ValueTreeRow.cs @@ -65,13 +65,15 @@ public ValueTree Owner() return _owner; } - private IValue TryValue(ValueTreeColumn column) - { - IValue value; - if (_data.TryGetValue(column, out value)) - return value; - return ValueFactory.Create(); // TODO: Определять пустое значение для типа колонки - } + private IValue TryValue(ValueTreeColumn column) + { + IValue value; + if (_data.TryGetValue(column, out value)) + { + return value; + } + return column.ValueType.AdjustValue(); + } /// /// Получает значение по индексу. @@ -96,28 +98,28 @@ public IValue Get(ValueTreeColumn column) return TryValue(column); } - /// - /// Устанавливает значение по индексу. - /// - /// Число. Индекс параметра, которому задаётся значение. - /// Произвольный. Новое значение. - [ContextMethod("Установить", "Set")] - public void Set(int index, IValue value) - { - var column = Owner().Columns.FindColumnByIndex(index); - _data[column] = value; - } - - public void Set(IValue index, IValue value) - { - var column = Owner().Columns.GetColumnByIIndex(index); - _data[column] = value; - } - - public void Set(ValueTreeColumn column, IValue value) - { - _data[column] = value; - } + /// + /// Устанавливает значение по индексу. + /// + /// Число. Индекс параметра, которому задаётся значение. + /// Произвольный. Новое значение. + [ContextMethod("Установить", "Set")] + public void Set(int index, IValue value) + { + var column = Owner().Columns.FindColumnByIndex(index); + _data[column] = column.ValueType.AdjustValue(value); + } + + public void Set(IValue index, IValue value) + { + var column = Owner().Columns.GetColumnByIIndex(index); + _data[column] = column.ValueType.AdjustValue(value); + } + + public void Set(ValueTreeColumn column, IValue value) + { + _data[column] = column.ValueType.AdjustValue(value); + } /// /// Возвращает уровень вложенности строки в дереве. @@ -183,7 +185,7 @@ public override void SetPropValue(int propNum, IValue newVal) } else { - _data[column] = newVal; + _data[column] = column.ValueType.AdjustValue(newVal); } } @@ -200,7 +202,8 @@ public override IValue GetIndexedValue(IValue index) public override void SetIndexedValue(IValue index, IValue val) { - _data[GetColumnByIIndex(index)] = val; + var column = GetColumnByIIndex(index); + _data[GetColumnByIIndex(index)] = column.ValueType.AdjustValue(val); } diff --git a/src/ScriptEngine.HostedScript/Library/Zip/ZipWriter.cs b/src/ScriptEngine.HostedScript/Library/Zip/ZipWriter.cs index 15a828987..83a5b46dc 100644 --- a/src/ScriptEngine.HostedScript/Library/Zip/ZipWriter.cs +++ b/src/ScriptEngine.HostedScript/Library/Zip/ZipWriter.cs @@ -56,6 +56,7 @@ public void Open( _zip.Comment = comment; _zip.CompressionMethod = MakeZipCompressionMethod(compressionMethod); _zip.CompressionLevel = MakeZipCompressionLevel(compressionLevel); + _zip.UseZip64WhenSaving = Zip64Option.AsNecessary; // Zlib падает с NullReferenceException, если задать шифрование //_zip.Encryption = MakeZipEncryption(encryptionMethod); } diff --git a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj index 2485e4c26..0775e0f35 100644 --- a/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj +++ b/src/ScriptEngine.HostedScript/ScriptEngine.HostedScript.csproj @@ -78,8 +78,8 @@ ..\packages\DotNetZip.1.9.3\lib\net20\Ionic.Zip.dll - - ..\packages\Newtonsoft.Json.9.0.1\lib\net40\Newtonsoft.Json.dll + + ..\packages\Newtonsoft.Json.10.0.3\lib\net40\Newtonsoft.Json.dll True @@ -94,6 +94,8 @@ GlobalAssemblyInfo.cs + + @@ -113,8 +115,8 @@ - + @@ -150,6 +152,7 @@ + @@ -160,7 +163,6 @@ - @@ -211,6 +213,7 @@ + diff --git a/src/ScriptEngine.HostedScript/packages.config b/src/ScriptEngine.HostedScript/packages.config index 4af8806b0..240e05d30 100644 --- a/src/ScriptEngine.HostedScript/packages.config +++ b/src/ScriptEngine.HostedScript/packages.config @@ -1,5 +1,5 @@  - + \ No newline at end of file diff --git a/src/ScriptEngine/Compiler/CompiledCodeIndexer.cs b/src/ScriptEngine/Compiler/CompiledCodeIndexer.cs index b0d5481c9..dc1dc1b04 100644 --- a/src/ScriptEngine/Compiler/CompiledCodeIndexer.cs +++ b/src/ScriptEngine/Compiler/CompiledCodeIndexer.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/ScriptEngine/Compiler/Compiler.cs b/src/ScriptEngine/Compiler/Compiler.cs index 0d6fc3fd5..0e4abf3fa 100644 --- a/src/ScriptEngine/Compiler/Compiler.cs +++ b/src/ScriptEngine/Compiler/Compiler.cs @@ -340,6 +340,13 @@ private void BuildSingleMethod() throw CompilerException.IdentifierExpected(); } + // issue #375 + if (String.Compare(_lastExtractedLexem.Content, "выполнить", StringComparison.OrdinalIgnoreCase) == 0 + || String.Compare(_lastExtractedLexem.Content, "execute", StringComparison.OrdinalIgnoreCase) == 0) + { + SystemLogger.Write($"WARNING! Method name '{_lastExtractedLexem.Content}' is DEPRECATED. Rename it"); + } + int definitionLine = _parser.CurrentLine; MethodInfo method = new MethodInfo(); method.Name = _lastExtractedLexem.Content; diff --git a/src/ScriptEngine/Compiler/ISourceCodeIndexer.cs b/src/ScriptEngine/Compiler/ISourceCodeIndexer.cs index e62a6348b..56a3a31de 100644 --- a/src/ScriptEngine/Compiler/ISourceCodeIndexer.cs +++ b/src/ScriptEngine/Compiler/ISourceCodeIndexer.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; namespace ScriptEngine.Compiler { interface ISourceCodeIndexer diff --git a/src/ScriptEngine/FormatParametersList.cs b/src/ScriptEngine/FormatParametersList.cs index 26e8e79e1..8f2687fe1 100644 --- a/src/ScriptEngine/FormatParametersList.cs +++ b/src/ScriptEngine/FormatParametersList.cs @@ -86,7 +86,7 @@ private static string ReadParameter(string format, ref int index) int start = index; while (index < format.Length) { - if (Char.IsLetter(format, index)) + if (Char.IsLetterOrDigit(format, index) || format[index] == '.' || format[index] == '_') index++; else if (format[index] == '=') { diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatData.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatData.cs new file mode 100644 index 000000000..4be4cb8bf --- /dev/null +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatData.cs @@ -0,0 +1,28 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ScriptEngine.Machine +{ + public struct CodeStatData + { + public readonly CodeStatEntry Entry; + public readonly long TimeElapsed; + public readonly int ExecutionCount; + + public CodeStatData(CodeStatEntry entry, long time, int count) + { + Entry = entry; + TimeElapsed = time; + ExecutionCount = count; + } + } +} diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatDataCollection.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatDataCollection.cs new file mode 100644 index 000000000..34cfaa878 --- /dev/null +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatDataCollection.cs @@ -0,0 +1,83 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace ScriptEngine.Machine +{ + public class CodeStatDataCollection : ICollection + { + private List entryList = new List(); + + public int Count + { + get + { + return entryList.Count(); + } + } + + public CodeStatData this[int index] + { + get + { + return entryList[index]; + } + set + { + entryList[index] = value; + } + } + + public bool IsReadOnly + { + get + { + return false; + } + } + + public void Add(CodeStatData item) + { + entryList.Add(item); + } + + public void Clear() + { + entryList.Clear(); + } + + public bool Contains(CodeStatData item) + { + return entryList.Contains(item); + } + + public void CopyTo(CodeStatData[] array, int arrayIndex) + { + entryList.CopyTo(array, arrayIndex); + } + + public bool Remove(CodeStatData item) + { + return entryList.Remove(item); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return entryList.GetEnumerator(); + } + + public IEnumerator GetEnumerator() + { + return entryList.GetEnumerator(); + } + } +} diff --git a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs index 5745e0f41..420c4324a 100644 --- a/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs +++ b/src/ScriptEngine/Machine/CodeStat/CodeStatProcessor.cs @@ -10,7 +10,6 @@ This Source Code Form is subject to the terms of the using System.Diagnostics; using System.Linq; using System.Collections.Generic; -using Newtonsoft.Json; namespace ScriptEngine.Machine { @@ -19,12 +18,10 @@ public class CodeStatProcessor : ICodeStatCollector private Dictionary _codeStat = new Dictionary(); private Dictionary _watchers = new Dictionary(); private Stopwatch _activeStopwatch = null; - private readonly string _outputFileName; private HashSet _preparedScripts = new HashSet(); - public CodeStatProcessor(string fileName) + public CodeStatProcessor() { - _outputFileName = fileName; } public bool IsPrepared(string ScriptFileName) @@ -53,59 +50,25 @@ public void MarkEntryReached(CodeStatEntry entry, int count = 1) } } - public void MarkPrepared(string ScriptFileName) + public void MarkPrepared(string scriptFileName) { - _preparedScripts.Add(ScriptFileName); + _preparedScripts.Add(scriptFileName); } - public void OutputCodeStat() + public CodeStatDataCollection GetStatData() { - _activeStopwatch?.Stop(); - - var w = new StreamWriter(_outputFileName); - var jwriter = new JsonTextWriter(w); - jwriter.Formatting = Formatting.Indented; - - jwriter.WriteStartObject(); - foreach (var source in _codeStat.GroupBy((arg) => arg.Key.ScriptFileName)) + CodeStatDataCollection data = new CodeStatDataCollection(); + foreach (var item in _codeStat) { - jwriter.WritePropertyName(source.Key, true); - jwriter.WriteStartObject(); - - jwriter.WritePropertyName("#path"); - jwriter.WriteValue(source.Key); - foreach (var method in source.GroupBy((arg) => arg.Key.SubName)) - { - jwriter.WritePropertyName(method.Key, true); - jwriter.WriteStartObject(); - - foreach (var entry in method.OrderBy((kv) => kv.Key.LineNumber)) - { - jwriter.WritePropertyName(entry.Key.LineNumber.ToString()); - jwriter.WriteStartObject(); - - jwriter.WritePropertyName("count"); - jwriter.WriteValue(entry.Value); - - if (_watchers.ContainsKey(entry.Key)) - { - var elapsed = _watchers[entry.Key].ElapsedMilliseconds; - - jwriter.WritePropertyName("time"); - jwriter.WriteValue(elapsed); - } - - jwriter.WriteEndObject(); - } - - jwriter.WriteEndObject(); - } - jwriter.WriteEndObject(); + data.Add(new CodeStatData(item.Key, _watchers[item.Key].ElapsedMilliseconds, item.Value)); } - jwriter.WriteEndObject(); - jwriter.Flush(); + + return data; + } - _codeStat.Clear(); + public void EndCodeStat() + { + _activeStopwatch?.Stop(); } public void StopWatch(CodeStatEntry entry) diff --git a/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs b/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs index 294f3bf0d..79e093d5a 100644 --- a/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs +++ b/src/ScriptEngine/Machine/CodeStat/ICodeStatCollector.cs @@ -11,7 +11,7 @@ public interface ICodeStatCollector { bool IsPrepared(string ScriptFileName); void MarkEntryReached(CodeStatEntry entry, int count = 1); - void MarkPrepared(string ScriptFileName); + void MarkPrepared(string scriptFileName); void StopWatch(CodeStatEntry entry); void ResumeWatch(CodeStatEntry entry); diff --git a/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs b/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs index 7eab34048..c55b3539c 100644 --- a/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs +++ b/src/ScriptEngine/Machine/Contexts/AttachedScriptsFactory.cs @@ -180,10 +180,10 @@ public static void Dispose() [ScriptConstructor(ParametrizeWithClassName = true)] public static IRuntimeContextInstance ScriptFactory(string typeName, IValue[] arguments) - { + { var module = _instance._loadedModules[typeName]; - var newObj = new UserScriptContextInstance(module, typeName); + var newObj = new UserScriptContextInstance(module, typeName, arguments); newObj.AddProperty("ЭтотОбъект", newObj); newObj.InitOwnData(); newObj.Initialize(_instance._engine.Machine); diff --git a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs index 1b2fb3810..79d0840e0 100644 --- a/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs +++ b/src/ScriptEngine/Machine/Contexts/COMWrapperContext.cs @@ -159,6 +159,10 @@ public static IValue CreateIValue(object objParam) { return ValueFactory.Create((decimal)(double)objParam); } + else if (type == typeof(decimal)) + { + return ValueFactory.Create((decimal)objParam); + } else if (type == typeof(DateTime)) { var unboxed = (DateTime)objParam; diff --git a/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs b/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs index 496beefa8..c5b420194 100644 --- a/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs +++ b/src/ScriptEngine/Machine/Contexts/ContextIValueImpl.cs @@ -146,6 +146,12 @@ public virtual void SetIndexedValue(IValue index, IValue val) { throw new NotImplementedException(); } + + public virtual IEnumerable GetProperties() + { + throw new NotImplementedException(); + } + public virtual int FindProperty(string name) { throw RuntimeException.PropNotFoundException(name); diff --git a/src/ScriptEngine/Machine/Contexts/EnumItemAttribute.cs b/src/ScriptEngine/Machine/Contexts/EnumItemAttribute.cs index 5257c27f9..9c7760fec 100644 --- a/src/ScriptEngine/Machine/Contexts/EnumItemAttribute.cs +++ b/src/ScriptEngine/Machine/Contexts/EnumItemAttribute.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; namespace ScriptEngine { [AttributeUsage(AttributeTargets.Field)] diff --git a/src/ScriptEngine/Machine/Contexts/LibraryContextBase.cs b/src/ScriptEngine/Machine/Contexts/LibraryContextBase.cs index 10117b246..2efdf3ac5 100644 --- a/src/ScriptEngine/Machine/Contexts/LibraryContextBase.cs +++ b/src/ScriptEngine/Machine/Contexts/LibraryContextBase.cs @@ -17,7 +17,7 @@ namespace ScriptEngine.Machine.Contexts public class LibraryContextBase : PropertyNameIndexAccessor, IReflectableContext { - public virtual IEnumerable GetProperties() + public override IEnumerable GetProperties() { throw new NotImplementedException(); } diff --git a/src/ScriptEngine/Machine/Contexts/ReflectableSDO.cs b/src/ScriptEngine/Machine/Contexts/ReflectableSDO.cs index 3dfef2bd4..ae2f4cda3 100644 --- a/src/ScriptEngine/Machine/Contexts/ReflectableSDO.cs +++ b/src/ScriptEngine/Machine/Contexts/ReflectableSDO.cs @@ -300,6 +300,11 @@ public void SetIndexedValue(IValue index, IValue val) _instance.SetIndexedValue(index, val); } + public IEnumerable GetProperties() + { + return _instance.GetProperties(); + } + public int FindProperty(string name) { return _instance.FindProperty(name); diff --git a/src/ScriptEngine/Machine/Contexts/SafeArrayWrapper.cs b/src/ScriptEngine/Machine/Contexts/SafeArrayWrapper.cs index 177033b05..e847e6940 100644 --- a/src/ScriptEngine/Machine/Contexts/SafeArrayWrapper.cs +++ b/src/ScriptEngine/Machine/Contexts/SafeArrayWrapper.cs @@ -58,6 +58,12 @@ public void SetValue(int index, IValue value) _array[index] = newValue; } + [ContextMethod("Выгрузить", "Unload")] + public object Unload() + { + throw new NotSupportedException("FIXME: Method 'Unload' is not supported. Consider use SafeArrayWrapper as V8.Array directly."); + } + public override IValue GetIndexedValue(IValue index) { var intIndex = (int)index.AsNumber(); diff --git a/src/ScriptEngine/Machine/Contexts/ScriptDrivenObject.cs b/src/ScriptEngine/Machine/Contexts/ScriptDrivenObject.cs index 63e8eb724..56639e35b 100644 --- a/src/ScriptEngine/Machine/Contexts/ScriptDrivenObject.cs +++ b/src/ScriptEngine/Machine/Contexts/ScriptDrivenObject.cs @@ -23,13 +23,25 @@ public abstract class ScriptDrivenObject : PropertyNameIndexAccessor, IAttachabl private readonly Dictionary _methodSearchCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private readonly Dictionary _propertySearchCache = new Dictionary(StringComparer.OrdinalIgnoreCase); + private IValue[] constructorParams = new IValue[0]; + + public IValue[] ConstructorParams { get { return constructorParams; } set { constructorParams = value; } } + + //~ScriptDrivenObject() + //{ + // var methId = GetScriptMethod("деструктор", "destructor"); + // if (methId > -1) + // { + // CallAsProcedure(methId, new IValue[0]); + // } + + public ScriptDrivenObject(LoadedModuleHandle module) : this(module.Module) { } public ScriptDrivenObject(LoadedModuleHandle module, bool deffered) : this(module.Module, deffered) { - } internal ScriptDrivenObject(LoadedModule module, bool deffered) @@ -106,6 +118,48 @@ public void Initialize(MachineInstance runner) _machine.AttachContext(this, true); _machine.ExecuteModuleBody(); }); + + var methId = GetScriptMethod("ПриСозданииОбъекта", "OnObjectCreate"); + int constructorParamsCount = ConstructorParams.Count(); + + if (methId > -1) + { + bool hasParamsError = false; + var procInfo = GetMethodInfo(methId); + + int procParamsCount = procInfo.Params.Count(); + + if (procParamsCount < constructorParamsCount) + { + hasParamsError = true; + } + + int reqParams = 0; + foreach(var itm in procInfo.Params) + { + if (!itm.HasDefaultValue) reqParams++; + } + if (reqParams > constructorParamsCount) + { + hasParamsError = true; + } + if (hasParamsError) + { + throw new RuntimeException("Параметры конструктора: " + + "необходимых параметров: " + Math.Min(procParamsCount, reqParams).ToString() + + ", передано параметров " + constructorParamsCount.ToString() + ); + } + + CallAsProcedure(methId, ConstructorParams); + } + else + { + if (constructorParamsCount > 0) + { + throw new RuntimeException("Конструктор не определен, но переданы параметры конструктора."); + } + } } protected int GetScriptMethod(string methodName, string alias = null) @@ -232,10 +286,7 @@ private MethodInfo[] AttachMethods() #region IReflectableContext Members - public virtual IEnumerable GetProperties() - { - throw new NotImplementedException(); - } + #endregion diff --git a/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs b/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs index 36fe63a6e..064b6db8a 100644 --- a/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs +++ b/src/ScriptEngine/Machine/Contexts/UserScriptContextInstance.cs @@ -18,16 +18,24 @@ public class UserScriptContextInstance : ScriptDrivenObject Dictionary _ownPropertyIndexes; List _ownProperties; + internal UserScriptContextInstance(LoadedModule module) : base(module) { _module = module; } - internal UserScriptContextInstance(LoadedModule module, string asObjectOfType) + internal UserScriptContextInstance(LoadedModule module, string asObjectOfType, IValue[] args = null) : base(module, true) { DefineType(TypeManager.GetTypeByName(asObjectOfType)); _module = module; + + ConstructorParams = args; + if (args == null) + { + ConstructorParams = new IValue[0]; + } + } public void AddProperty(string name, IValue value) diff --git a/src/ScriptEngine/Machine/ExternalContextData.cs b/src/ScriptEngine/Machine/ExternalContextData.cs index 94e677523..ace45b020 100644 --- a/src/ScriptEngine/Machine/ExternalContextData.cs +++ b/src/ScriptEngine/Machine/ExternalContextData.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/ScriptEngine/Machine/ExternalSystemException.cs b/src/ScriptEngine/Machine/ExternalSystemException.cs index 37cdea325..3c4e806bb 100644 --- a/src/ScriptEngine/Machine/ExternalSystemException.cs +++ b/src/ScriptEngine/Machine/ExternalSystemException.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; namespace ScriptEngine.Machine { @@ -9,4 +15,4 @@ public ExternalSystemException(Exception reason) { } } -} \ No newline at end of file +} diff --git a/src/ScriptEngine/Machine/IRuntimeContextInstance.cs b/src/ScriptEngine/Machine/IRuntimeContextInstance.cs index b52281dfb..acdd8b83e 100644 --- a/src/ScriptEngine/Machine/IRuntimeContextInstance.cs +++ b/src/ScriptEngine/Machine/IRuntimeContextInstance.cs @@ -19,6 +19,7 @@ public interface IRuntimeContextInstance IValue GetIndexedValue(IValue index); void SetIndexedValue(IValue index, IValue val); + IEnumerable GetProperties(); int FindProperty(string name); bool IsPropReadable(int propNum); bool IsPropWritable(int propNum); diff --git a/src/ScriptEngine/Machine/MachineInstance.cs b/src/ScriptEngine/Machine/MachineInstance.cs index 23a9e8af7..d7b01b4ee 100644 --- a/src/ScriptEngine/Machine/MachineInstance.cs +++ b/src/ScriptEngine/Machine/MachineInstance.cs @@ -1747,35 +1747,10 @@ private void StrGetLine(int arg) string result = ""; if (lineNumber >= 1) { - int lineStart = 0; - int currentLineNumber = 1; - while (true) - { - int lineEnd = strArg.IndexOf('\n', lineStart); - if (lineEnd > 0) - { - if (currentLineNumber == lineNumber) - { - if (lineEnd > lineStart) - result = strArg.Substring(lineStart, lineEnd - lineStart); - - break; - } - - lineStart = lineEnd + 1; - currentLineNumber++; - } - else - { - if (currentLineNumber == lineNumber) - { - result = strArg.Substring(lineStart); - } - break; - } - } + string[] subStrVals = strArg.Split(new Char[] { '\n' }, lineNumber + 1); + result = subStrVals[lineNumber - 1]; } - + _operationStack.Push(ValueFactory.Create(result)); NextInstruction(); } diff --git a/src/ScriptEngine/Machine/TypeManager.cs b/src/ScriptEngine/Machine/TypeManager.cs index f24832f20..b9a05bb5a 100644 --- a/src/ScriptEngine/Machine/TypeManager.cs +++ b/src/ScriptEngine/Machine/TypeManager.cs @@ -117,8 +117,10 @@ public TypeDescriptor RegisterType(string name, Type implementingClass) if (_knownTypesIndexes.ContainsKey(name)) { var td = GetTypeByName(name); - if (GetImplementingClass(td.ID) != implementingClass) - throw new InvalidOperationException("Name already registered"); + if (GetImplementingClass(td.ID) != implementingClass) + { + throw new InvalidOperationException(string.Format("Name `{0}` is already registered", name)); + } return td; } diff --git a/src/ScriptEngine/ScriptEngine.csproj b/src/ScriptEngine/ScriptEngine.csproj index db5d4deef..468fa5e46 100644 --- a/src/ScriptEngine/ScriptEngine.csproj +++ b/src/ScriptEngine/ScriptEngine.csproj @@ -85,9 +85,6 @@ - - ..\packages\Newtonsoft.Json.9.0.1\lib\net40\Newtonsoft.Json.dll - @@ -112,6 +109,8 @@ + + @@ -196,12 +195,7 @@ - - - - - - + diff --git a/src/ScriptEngine/packages.config b/src/ScriptEngine/packages.config deleted file mode 100644 index 101fdf5c4..000000000 --- a/src/ScriptEngine/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/src/TestApp/EditedFileSource.cs b/src/TestApp/EditedFileSource.cs index 79a9c26c8..0eb0f0c28 100644 --- a/src/TestApp/EditedFileSource.cs +++ b/src/TestApp/EditedFileSource.cs @@ -1,4 +1,10 @@ -using System; +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; using System.Collections.Generic; using System.Linq; using System.Text; diff --git a/src/oscript/CgiBehavior.cs b/src/oscript/CgiBehavior.cs index 232df4ffd..33f78d21d 100644 --- a/src/oscript/CgiBehavior.cs +++ b/src/oscript/CgiBehavior.cs @@ -12,6 +12,7 @@ This Source Code Form is subject to the terms of the using System; using System.Collections.Generic; using System.Linq; +using System.IO; using System.Text; namespace oscript @@ -29,10 +30,10 @@ public CgiBehavior() public override int Execute() { string scriptFile; - scriptFile = Environment.GetEnvironmentVariable("PATH_TRANSLATED"); + scriptFile = Environment.GetEnvironmentVariable("SCRIPT_FILENAME"); if (scriptFile == null) { - scriptFile = Environment.GetEnvironmentVariable("SCRIPT_FILENAME"); + scriptFile = Environment.GetEnvironmentVariable("PATH_TRANSLATED"); } if (scriptFile == null) @@ -99,6 +100,36 @@ public void Header(string header, string value) _headersWritten.Add(header); } + [ContextMethod("ОтправитьФайл", "SendFile")] + public void SendFile(string filePath, string downloadFileName = null) + { + if (_isContentEchoed) + { + throw new InvalidOperationException("Content already sent!"); + } + + if (!IsHeaderWritten("Content-type")) + { + Header("Content-type", "application/octet-stream"); + } + if (string.IsNullOrEmpty(downloadFileName)) + { + var finfo = new FileInfo(filePath); + downloadFileName = finfo.Name; + } + using (var fs = new FileStream(filePath, FileMode.Open)) + { + Header("Content-disposition", string.Format("inline; filename=\"{0}\"", downloadFileName)); + Header("Content-length", fs.Length.ToString()); + oscript.Output.WriteLine(); + + using (var stdout = Console.OpenStandardOutput()) + { + fs.CopyTo(stdout); + } + } + } + public Encoding Encoding { get; set; } private bool IsHeaderWritten(string header) diff --git a/src/oscript/CheckSyntaxBehavior.cs b/src/oscript/CheckSyntaxBehavior.cs index 88a0d2318..d5bf31e01 100644 --- a/src/oscript/CheckSyntaxBehavior.cs +++ b/src/oscript/CheckSyntaxBehavior.cs @@ -41,6 +41,8 @@ public override int Execute() ScriptFileHelper.OnBeforeScriptRead(hostedScript); var source = hostedScript.Loader.FromFile(_path); + hostedScript.SetGlobalEnvironment(new DoNothingHost(), source); + try { if(_envFile != null) diff --git a/src/oscript/CodeStatWriter.cs b/src/oscript/CodeStatWriter.cs new file mode 100644 index 000000000..e99dd84d9 --- /dev/null +++ b/src/oscript/CodeStatWriter.cs @@ -0,0 +1,87 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ + +using System; +using System.IO; +using System.Linq; +using ScriptEngine.Machine; +using Newtonsoft.Json; + +namespace oscript +{ + public class CodeStatWriter + { + private readonly CodeStatWriterType _type; + private readonly string _outputFileName; + + public CodeStatWriter(string fileName, CodeStatWriterType type) + { + _outputFileName = fileName; + _type = type; + } + + public void Write(CodeStatDataCollection codeStatDataCollection) + { + if (_type == CodeStatWriterType.JSON) + { + writeToJson(codeStatDataCollection); + } + else + { + throw new ArgumentException("Unsupported type"); + } + } + + private void writeToJson(CodeStatDataCollection codeStatDataCollection) + { + using (var w = new StreamWriter(_outputFileName)) + { + var jwriter = new JsonTextWriter(w); + jwriter.Formatting = Formatting.Indented; + + jwriter.WriteStartObject(); + foreach (var source in codeStatDataCollection.GroupBy((arg) => arg.Entry.ScriptFileName)) + { + jwriter.WritePropertyName(source.Key, true); + jwriter.WriteStartObject(); + + jwriter.WritePropertyName("#path"); + jwriter.WriteValue(source.Key); + foreach (var method in source.GroupBy((arg) => arg.Entry.SubName)) + { + jwriter.WritePropertyName(method.Key, true); + jwriter.WriteStartObject(); + + foreach (var entry in method.OrderBy((kv) => kv.Entry.LineNumber)) + { + jwriter.WritePropertyName(entry.Entry.LineNumber.ToString()); + jwriter.WriteStartObject(); + + jwriter.WritePropertyName("count"); + jwriter.WriteValue(entry.ExecutionCount); + + jwriter.WritePropertyName("time"); + jwriter.WriteValue(entry.TimeElapsed); + + jwriter.WriteEndObject(); + } + + jwriter.WriteEndObject(); + } + jwriter.WriteEndObject(); + } + jwriter.WriteEndObject(); + jwriter.Flush(); + } + } + } + //TODO: Добавить другие форматы записи + public enum CodeStatWriterType + { + JSON + } +} diff --git a/src/oscript/DoNothingHost.cs b/src/oscript/DoNothingHost.cs new file mode 100644 index 000000000..2f7d240a6 --- /dev/null +++ b/src/oscript/DoNothingHost.cs @@ -0,0 +1,43 @@ +/*---------------------------------------------------------- +This Source Code Form is subject to the terms of the +Mozilla Public License, v.2.0. If a copy of the MPL +was not distributed with this file, You can obtain one +at http://mozilla.org/MPL/2.0/. +----------------------------------------------------------*/ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using ScriptEngine.HostedScript; +using ScriptEngine.HostedScript.Library; + +namespace oscript +{ + class DoNothingHost : IHostApplication + { + public void Echo(string str, MessageStatusEnum status = MessageStatusEnum.Ordinary) + { + + } + + public void ShowExceptionInfo(Exception exc) + { + + } + + public bool InputString(out string result, int maxLen) + { + result = ""; + return true; + } + + public string[] GetCommandLineArguments() + { + return new[] + { + "" + }; + } + } +} diff --git a/src/oscript/ExecuteScriptBehavior.cs b/src/oscript/ExecuteScriptBehavior.cs index 8d09fd0d6..f060d4745 100644 --- a/src/oscript/ExecuteScriptBehavior.cs +++ b/src/oscript/ExecuteScriptBehavior.cs @@ -56,6 +56,8 @@ public override int Execute() var result = process.Start(); hostedScript.Finalize(); + ScriptFileHelper.OnAfterScriptExecute(hostedScript); + return result; } diff --git a/src/oscript/ScriptFileHelper.cs b/src/oscript/ScriptFileHelper.cs index 27b9d17ff..941b5a427 100644 --- a/src/oscript/ScriptFileHelper.cs +++ b/src/oscript/ScriptFileHelper.cs @@ -111,7 +111,17 @@ public static void OnBeforeScriptRead(HostedScriptEngine engine) } if (CodeStatisticsEnabled) - engine.EnableCodeStatistics(CodeStatisticsFileName); + engine.EnableCodeStatistics(); + } + + public static void OnAfterScriptExecute(HostedScriptEngine engine) + { + if (CodeStatisticsEnabled) + { + var codeStat = engine.GetCodeStatData(); + CodeStatWriter statsWriter = new CodeStatWriter(CodeStatisticsFileName, CodeStatWriterType.JSON); + statsWriter.Write(codeStat); + } } } } diff --git a/src/oscript/ShowCompiledBehavior.cs b/src/oscript/ShowCompiledBehavior.cs index 7fa39ee96..5e608820f 100644 --- a/src/oscript/ShowCompiledBehavior.cs +++ b/src/oscript/ShowCompiledBehavior.cs @@ -30,6 +30,7 @@ public override int Execute() ScriptFileHelper.OnBeforeScriptRead(hostedScript); var source = hostedScript.Loader.FromFile(_path); var compiler = hostedScript.GetCompilerService(); + hostedScript.SetGlobalEnvironment(new DoNothingHost(), source); var writer = new ScriptEngine.Compiler.ModuleWriter(compiler); try { diff --git a/src/oscript/ShowUsageBehavior.cs b/src/oscript/ShowUsageBehavior.cs index 017dbebd0..3e35c5874 100644 --- a/src/oscript/ShowUsageBehavior.cs +++ b/src/oscript/ShowUsageBehavior.cs @@ -25,7 +25,7 @@ public override int Execute() Output.WriteLine("Mode can be one of these:"); Output.WriteLine(String.Format(" {0,-12}measures execution time", "-measure")); Output.WriteLine(String.Format(" {0,-12}shows compiled module without execution", "-compile")); - Output.WriteLine(String.Format(" {0,-12}provides syntax check", "-check")); + Output.WriteLine(String.Format(" {0,-12}provides syntax check", "-check [-env=]")); Output.WriteLine(String.Format(" {0,-12}provides syntax check in CGI-mode", "-check -cgi")); Output.WriteLine(); Output.WriteLine(String.Format(" {0} set output encoding", "-encoding=")); diff --git a/src/oscript/oscript.csproj b/src/oscript/oscript.csproj index 53ef2012e..30a32b939 100644 --- a/src/oscript/oscript.csproj +++ b/src/oscript/oscript.csproj @@ -77,6 +77,10 @@ MinimumRecommendedRules.ruleset + + ..\packages\Newtonsoft.Json.10.0.3\lib\net40\Newtonsoft.Json.dll + True + @@ -94,7 +98,9 @@ + + @@ -130,6 +136,9 @@ + + + diff --git a/src/oscript/packages.config b/src/oscript/packages.config new file mode 100644 index 000000000..03c709252 --- /dev/null +++ b/src/oscript/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/tests/StrGetLine.os b/tests/StrGetLine.os new file mode 100644 index 000000000..a94c635c2 --- /dev/null +++ b/tests/StrGetLine.os @@ -0,0 +1,60 @@ +Перем юТест; +Перем Данные; + +Процедура Инициализация() + Данные = + " + |Стр2 + |Стр3 + |Стр4 + | + |Стр6 + |Стр7 + |Стр8 + | + |Стр10"; +КонецПроцедуры + +Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт + + юТест = ЮнитТестирование; + + ВсеТесты = Новый Массив; + + ВсеТесты.Добавить("ТестДолжен_ВернутьСтроку1"); + ВсеТесты.Добавить("ТестДолжен_ВернутьСтроку2"); + ВсеТесты.Добавить("ТестДолжен_ВернутьСтроку5"); + ВсеТесты.Добавить("ТестДолжен_ВернутьСтроку10"); + + Возврат ВсеТесты; +КонецФункции + +Процедура ТестДолжен_ВернутьСтроку1() Экспорт + + Стр = СтрПолучитьСтроку(Данные, 1); + + юТест.ПроверитьРавенство("", Стр); +КонецПроцедуры + +Процедура ТестДолжен_ВернутьСтроку2() Экспорт + + Стр = СтрПолучитьСтроку(Данные, 2); + + юТест.ПроверитьРавенство("Стр2", Стр); +КонецПроцедуры + +Процедура ТестДолжен_ВернутьСтроку5() Экспорт + + Стр = СтрПолучитьСтроку(Данные, 5); + + юТест.ПроверитьРавенство("", Стр); +КонецПроцедуры + +Процедура ТестДолжен_ВернутьСтроку10() Экспорт + + Стр = СтрПолучитьСтроку(Данные, 10); + + юТест.ПроверитьРавенство("Стр10", Стр); +КонецПроцедуры + +Инициализация(); \ No newline at end of file diff --git a/tests/addin.os b/tests/addin.os new file mode 100644 index 000000000..b42dea676 --- /dev/null +++ b/tests/addin.os @@ -0,0 +1,52 @@ +#Использовать "component" + +Перем юТест; + +Функция ПолучитьСписокТестов(Знач Тесты) Экспорт + + юТест = Тесты; + + Список = Новый Массив; + Список.Добавить("ТестДолжен_ПроверитьПодключениеГлобальногоКонтекста"); + + Возврат Список; + +КонецФункции + +Функция ВернутьПеречисление(Значение) + + Возврат Значение; + +КонецФункции + +Процедура ТестДолжен_ПроверитьПодключениеГлобальногоКонтекста() Экспорт + + Коллекция1 = Новый ПростоКоллекция; // Объект создаётся + + Объект1 = Новый ПростоКласс; + Объект2 = Новый ПростоКласс(4); // Разные конструкторы + + юТест.ПроверитьНеРавенство(Объект1.ЦелочисленноеСвойство, Объект2.ЦелочисленноеСвойство); + юТест.ПроверитьРавенство(Объект2.ЦелочисленноеСвойство, 4); + + Коллекция1.Добавить(Объект1); + + юТест.ПроверитьРавенство(Коллекция1.Количество(), 1); + + // Обход по коллекции + Для Каждого мОбъект Из Коллекция1 Цикл + + юТест.ПроверитьРавенство(мОбъект, Объект1); + + КонецЦикла; + + // Перечисление в глобальном контексте + Объект1.СвойствоПеречисление = ПростоПеречисление.Элемент1; + + юТест.ПроверитьРавенство(Объект1.СвойствоПеречисление, ПростоПеречисление.Элемент1); + юТест.ПроверитьНеРавенство(Объект1.СвойствоПеречисление, ПростоПеречисление.Элемент2); + + // Работа маршаллера + юТест.ПроверитьРавенство(ВернутьПеречисление(Объект1.СвойствоПеречисление), ПростоПеречисление.Элемент1); + +КонецПроцедуры diff --git a/tests/codestat.os b/tests/codestat.os index 4de6ef42f..ed0e930ed 100644 --- a/tests/codestat.os +++ b/tests/codestat.os @@ -51,7 +51,7 @@ Функция ПолучитьВыводДляСкрипта(Знач ИмяФайлаОСкрипта) - ИмяФайлаВывода = ЗапуститьФайлСкрипта(ИмяФайлаОСкрипта); + ИмяФайлаВывода = ЗапуститьФайлСкрипта(""""+ИмяФайлаОСкрипта+""""); Чтение = Новый ЧтениеJson(); Чтение.ОткрытьФайл(ИмяФайлаВывода, "UTF-8"); @@ -88,13 +88,12 @@ ИмяФайлаСистемногоСкриптаЗапуска = ПолучитьИмяВременногоФайла("sh"); ЗаписьТекста = Новый ЗаписьТекста(ИмяФайлаСистемногоСкриптаЗапуска,,,, Символы.ПС); - ЗаписьТекста.ЗаписатьСтроку("bash -s << /dev/null" ); - ЗаписьТекста.ЗаписатьСтроку("CALLEOF"); ЗаписьТекста.Закрыть(); СтрокаЗапуска = "bash " + ИмяФайлаСистемногоСкриптаЗапуска; @@ -103,9 +102,16 @@ Процесс = СоздатьПроцесс(СтрокаЗапуска,,Истина); Процесс.Запустить(); + + Пока Не Процесс.Завершен ИЛИ Процесс.ПотокВывода.ЕстьДанные Цикл + Стр = Процесс.ПотокВывода.Прочитать(); + Если Стр <> Неопределено Тогда + Сообщить(Стр); + КонецЕсли; + КонецЦикла; - Процесс.ОжидатьЗавершения(); - + юТест.ПроверитьРавенство(0, Процесс.КодВозврата, "Процесс должен был завершиться успешно"); + УдалитьФайлы(ИмяФайлаСистемногоСкриптаЗапуска); Возврат ИмяФайлаВывода; diff --git a/tests/component/package-loader.os b/tests/component/package-loader.os new file mode 100644 index 000000000..7f79f0d1f --- /dev/null +++ b/tests/component/package-loader.os @@ -0,0 +1,7 @@ + +Процедура ПриЗагрузкеБиблиотеки(Знач Путь, СтандартнаяОбработка, Отказ) + + СтандартнаяОбработка = Ложь; + ПодключитьВнешнююКомпоненту(ОбъединитьПути(Путь, "Component.dll")); + +КонецПроцедуры diff --git a/tests/constructor.os b/tests/constructor.os new file mode 100644 index 000000000..0c174c6f3 --- /dev/null +++ b/tests/constructor.os @@ -0,0 +1,72 @@ +#Использовать asserts +#Использовать logos + +Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт + + ВсеТесты = Новый Массив; + + ВсеТесты.Добавить("ТестДолжен_СообщитьОбОшибкеНетКонструктора"); + ВсеТесты.Добавить("ТестДолжен_СообщитьОбОшибкеСлишкомМногоПараметров"); + ВсеТесты.Добавить("ТестДолжен_СообщитьОбОшибкеСлишкомМалоПараметров"); + ВсеТесты.Добавить("ТестДолжен_СоздатьОбъект"); + ВсеТесты.Добавить("ТестДолжен_СоздатьОбъектЛог"); + + Возврат ВсеТесты; + +КонецФункции + +Процедура ТестДолжен_СообщитьОбОшибкеНетКонструктора() Экспорт + + Попытка + ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; + ПодключитьСценарий(ОбъединитьПути(ТекПуть,"testdata", "no-magic-object.os") , "ПроверкаБезКонструктора"); + + НовыйОбъект = Новый ПроверкаБезКонструктора(1); + Исключение + Ожидаем.Что(ОписаниеОшибки()).Содержит("Конструктор не определен"); + КонецПопытки; + +КонецПроцедуры + +Процедура ТестДолжен_СообщитьОбОшибкеСлишкомМногоПараметров() Экспорт + + Попытка + ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; + ПодключитьСценарий(ОбъединитьПути(ТекПуть,"testdata", "magic-object.os") , "Проверка"); + + НовыйОбъект = Новый Проверка(1, 2, 3, 4, 5); + + Исключение + Ожидаем.Что(ОписаниеОшибки()).Содержит("необходимых параметров: 3, передано параметров 5"); + КонецПопытки; + +КонецПроцедуры + +Процедура ТестДолжен_СообщитьОбОшибкеСлишкомМалоПараметров() Экспорт + + Попытка + ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; + ПодключитьСценарий(ОбъединитьПути(ТекПуть,"testdata", "magic-object.os") , "Проверка"); + + НовыйОбъект = Новый Проверка(1, 2); + + Исключение + Ожидаем.Что(ОписаниеОшибки()).Содержит("необходимых параметров: 3, передано параметров 2"); + КонецПопытки; + +КонецПроцедуры + +Процедура ТестДолжен_СоздатьОбъект() Экспорт + + ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; + ПодключитьСценарий(ОбъединитьПути(ТекПуть,"testdata", "magic-object.os") , "Проверка"); + + НовыйОбъект = Новый Проверка(1, 2, 3); + +КонецПроцедуры + +Процедура ТестДолжен_СоздатьОбъектЛог() Экспорт + + НовыйОбъект = Новый Лог(); + +КонецПроцедуры diff --git a/tests/driveinfo.os b/tests/driveinfo.os new file mode 100644 index 000000000..dfe4f39d7 --- /dev/null +++ b/tests/driveinfo.os @@ -0,0 +1,88 @@ +#Использовать asserts + +Функция ПолучитьСписокТестов(Тестирование) Экспорт + + СписокТестов = Новый Массив; + СписокТестов.Добавить("Тест_Должен_ВернутьДоступноеМесто"); + СписокТестов.Добавить("Тест_Должен_ВернутьИмяФС"); + СписокТестов.Добавить("Тест_Должен_ВернутьТипДиска"); + СписокТестов.Добавить("Тест_Должен_ВернутьГотов"); + СписокТестов.Добавить("Тест_Должен_ВернутьИмя"); + СписокТестов.Добавить("Тест_Должен_ВернутьКорневойКаталог"); + СписокТестов.Добавить("Тест_Должен_ВернутьОбщийОбъемСвободногоМеста"); + СписокТестов.Добавить("Тест_Должен_ВернутьРазмерДиска"); + СписокТестов.Добавить("Тест_Должен_ВернутьМеткаТома"); + + СписокТестов.Добавить("Тест_Должен_ВывестиЗначения"); + + Возврат СписокТестов; + +КонецФункции + +Функция ПодключенныйДиск() + Диски = Новый СистемнаяИнформация().ИменаЛогическихДисков; + Для Каждого Диск из Диски Цикл + ИнформацияОДиске = Новый ИнформацияОДиске(Диск); + Если ИнформацияОДиске.Готов Тогда + Возврат ИнформацияОДиске; + КонецЕсли; + КонецЦикла; +КонецФункции + +Процедура Тест_Должен_ВернутьДоступноеМесто() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Ожидаем.Что(ИнформацияОДиске.Доступно).Больше(0); +КонецПроцедуры + +Процедура Тест_Должен_ВернутьИмяФС() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Ожидаем.Что(ИнформацияОДиске.ИмяФС).ЭтоНе().Равно(""); +КонецПроцедуры + +Процедура Тест_Должен_ВернутьТипДиска() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Ожидаем.Что(ИнформацияОДиске.ТипДиска).ЭтоНе().Равно(""); +КонецПроцедуры + +Процедура Тест_Должен_ВернутьГотов() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Ожидаем.Что(ИнформацияОДиске.Готов).ЭтоИстина(); +КонецПроцедуры + +Процедура Тест_Должен_ВернутьИмя() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Ожидаем.Что(ИнформацияОДиске.Имя).ЭтоНе().Равно(""); +КонецПроцедуры + +Процедура Тест_Должен_ВернутьКорневойКаталог() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Ожидаем.Что(ИнформацияОДиске.КорневойКаталог.Путь).ЭтоНе().Равно(""); +КонецПроцедуры + +Процедура Тест_Должен_ВернутьОбщийОбъемСвободногоМеста() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Ожидаем.Что(ИнформацияОДиске.ОбщийОбъемСвободногоМеста).Больше(0); +КонецПроцедуры + +Процедура Тест_Должен_ВернутьРазмерДиска() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Ожидаем.Что(ИнформацияОДиске.РазмерДиска).Больше(0); +КонецПроцедуры + +Процедура Тест_Должен_ВернутьМеткаТома() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Ожидаем.Что(ИнформацияОДиске.МеткаТома).Существует(); +КонецПроцедуры + +Процедура Тест_Должен_ВывестиЗначения() Экспорт + ИнформацияОДиске = ПодключенныйДиск(); + Сообщить("Доступно: " + ИнформацияОДиске.Доступно); + Сообщить("ИмяФС: " + ИнформацияОДиске.ИмяФС); + Сообщить("ТипДиска: " + ИнформацияОДиске.ТипДиска); + Сообщить("Готов: " + ИнформацияОДиске.Готов); + Сообщить("Имя: " + ИнформацияОДиске.Имя); + Сообщить("КорневойКаталог.Путь: " + ИнформацияОДиске.КорневойКаталог.Путь); + Сообщить("ОбщийОбъемСвободногоМеста: " + ИнформацияОДиске.ОбщийОбъемСвободногоМеста); + Сообщить("РазмерДиска: " + ИнформацияОДиске.РазмерДиска); + Сообщить("МеткаТома: " + ИнформацияОДиске.МеткаТома); +КонецПроцедуры \ No newline at end of file diff --git a/tests/engine-behaviors.os b/tests/engine-behaviors.os index 28552eacd..244668787 100644 --- a/tests/engine-behaviors.os +++ b/tests/engine-behaviors.os @@ -40,6 +40,7 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоВозможноИспользоватьПараметрыОбычногоИсключения"); ВсеТесты.Добавить("ТестДолжен_ПроверитьПередачуПеречисленийЧерезПараметры"); ВсеТесты.Добавить("ТестДолжен_ПроверитьКомпиляциюКлючевыхСловВСвойствахСтруктуры"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоАргументыКоманднойСтрокиЭтоФиксированныйМассив"); Возврат ВсеТесты; @@ -390,3 +391,9 @@ юТест.ПроверитьРавенство(Null, Структура.Null, "Null"); КонецПроцедуры + +Процедура ТестДолжен_ПроверитьЧтоАргументыКоманднойСтрокиЭтоФиксированныйМассив() Экспорт + + юТест.ПроверитьРавенство(ТипЗнч(АргументыКоманднойСтроки), Тип("ФиксированныйМассив"), "Аргументы командной строки - фиксированный массив"); + +КонецПроцедуры diff --git a/tests/environment-variables.os b/tests/environment-variables.os new file mode 100644 index 000000000..0a1821a24 --- /dev/null +++ b/tests/environment-variables.os @@ -0,0 +1,49 @@ +/////////////////////////////////////////////////////////////////////// +// +// Тест класса СистемнаяИнформация +// +// +/////////////////////////////////////////////////////////////////////// + +Перем юТест; + +//////////////////////////////////////////////////////////////////// +// Программный интерфейс + +Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт + + юТест = ЮнитТестирование; + + ВсеТесты = Новый Массив; + + ВсеТесты.Добавить("ТестДолжен_ПолучитьЗначенияОкружения"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПеременнуюPATH"); + ВсеТесты.Добавить("ТестДолжен_УстановитьПеременную"); + + Возврат ВсеТесты; +КонецФункции + +Процедура ТестДолжен_ПолучитьЗначенияОкружения() Экспорт + + Переменные = ПеременныеСреды(); + + юТест.ПроверитьЛожь(Переменные.Количество() = 0); + +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПеременнуюPATH() Экспорт + + юТест.ПроверитьЛожь(ПустаяСтрока(ПолучитьПеременнуюСреды("PATH"))); + +КонецПроцедуры + +Процедура ТестДолжен_УстановитьПеременную() Экспорт + + СтароеЗначение = ПолучитьПеременнуюСреды("OS"); + НовоеЗначение = "NewTestValue"; + + УстановитьПеременнуюСреды("OS", НовоеЗначение); + + юТест.ПроверитьРавенство(НовоеЗначение, ПолучитьПеременнуюСреды("OS")); + +КонецПроцедуры \ No newline at end of file diff --git a/tests/example-test.os b/tests/example-test.os index 104638f54..e38b0a758 100644 --- a/tests/example-test.os +++ b/tests/example-test.os @@ -1,4 +1,8 @@ Перем юТест; +Перем ЭтотОбъек Экспорт; +Перем ЭкспортнаяПеременная Экспорт; +Перем Яшма1 Экспорт; +Перем Яшма2; Функция Версия() Экспорт Возврат "0.1"; diff --git a/tests/global-funcs.os b/tests/global-funcs.os index 6b7c4a8d2..fff8be2e6 100644 --- a/tests/global-funcs.os +++ b/tests/global-funcs.os @@ -64,6 +64,7 @@ ВсеТесты.Добавить("Тест_ДолженПроверитьДекодированиеURLвКодировкеURL"); ВсеТесты.Добавить("Тест_ДолженПроверитьЧтоПоискФайловВНеизвестномКаталогеВозвращаетПустойМассив"); + ВсеТесты.Добавить("Тест_ДолженПроверитьЧтоУдалениеВНеизвестномКаталогеНеПадает"); ВсеТесты.Добавить("Тест_ДолженПроверитьЧтоПоискФайловПоИмениСуществующегоФайлаВозвращаетМассив"); ВсеТесты.Добавить("Тест_ДолженПроверитьЧтоПоискФайловРаботает"); //ВсеТесты.Добавить("Тест_ДолженПроверитьЧтоПоискФайловРазрешаетСсылкиВПутях"); @@ -579,6 +580,25 @@ КонецПроцедуры +Процедура Тест_ДолженПроверитьЧтоУдалениеВНеизвестномКаталогеНеПадает() Экспорт + + СИ = Новый СистемнаяИнформация(); + Если Найти(СИ.ВерсияОС,"Windows") > 0 Тогда + Каталог = "C:\нет такого пути"; + Иначе + Каталог = "/none/path"; + КонецЕсли; + + // На всякий случай, проверим, вдруг каталог есть + Файл = Новый Файл(Каталог); + Если Файл.Существует() Тогда + ВызватьИсключение "В текущем окружении каталог " + Каталог + " существует. Не выполняем тест"; + КонецЕсли; + + УдалитьФайлы(Каталог, "*.txt"); + +КонецПроцедуры + Процедура Тест_ДолженПроверитьЧтоПоискФайловПоИмениСуществующегоФайлаВозвращаетМассив() Экспорт ВФ = юТест.ИмяВременногоФайла(); diff --git a/tests/http.os b/tests/http.os index c43a14edb..5c3714822 100644 --- a/tests/http.os +++ b/tests/http.os @@ -174,7 +174,7 @@ Запрос = Новый HttpЗапрос("/get"); Соединение = Новый HttpСоединение(мАдресРесурса); - Ответ = Соединение.ВызватьHTTPМетод("UNKNOWN", Запрос); + Ответ = Соединение.ВызватьHTTPМетод("POST", Запрос); юТест.ПроверитьРавенство(405, Ответ.КодСостояния); юТест.ПроверитьВхождение(Ответ.ПолучитьТелоКакСтроку(), "Method Not Allowed"); @@ -199,4 +199,4 @@ /// ИНИЦИАЛИЗАЦИЯ /////////////////////////////////////////////////////////////////// -мАдресРесурса = "httpbin.org"; \ No newline at end of file +мАдресРесурса = "httpbin.org"; diff --git a/tests/managed-com.os b/tests/managed-com.os index 91690ae98..cb3f24989 100644 --- a/tests/managed-com.os +++ b/tests/managed-com.os @@ -11,7 +11,7 @@ ВсеТесты = Новый Массив; СИ = Новый СистемнаяИнформация; - Если (Найти(СИ.ВерсияОС, "Windows") > 0) И Не (СИ.ПеременныеСреды().Получить("APPVEYOR") = "True") Тогда + Если (Найти(СИ.ВерсияОС, "Windows") > 0) И Не (ПеременныеСреды().Получить("APPVEYOR") = "True") Тогда ВсеТесты.Добавить("ТестДолжен_ПроверитьУстановкуЧисловыхСвойств"); ВсеТесты.Добавить("ТестДолжен_ПроверитьВызовСОпциональнымиПараметрами"); КонецЕсли; diff --git a/tests/process.os b/tests/process.os index 60093f701..395317b7a 100644 --- a/tests/process.os +++ b/tests/process.os @@ -12,6 +12,7 @@ Если Найти(СИ.ВерсияОС, "Windows") > 0 Тогда ВсеТесты.Добавить("ТестДолжен_ПрочитатьВыводOscriptСразу"); ВсеТесты.Добавить("ТестДолжен_ПрочитатьВыводOscriptПострочно"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоМетодПрочитатьНаПустомПотокеВернетНеопределено"); ВсеТесты.Добавить("ТестДолжен_ЗаписатьВоВходнойПотокПроцесса"); ВсеТесты.Добавить("ТестДолжен_НайтиПроцессПоИмени"); ВсеТесты.Добавить("ТестДолжен_НайтиПроцессПоPID"); @@ -133,7 +134,7 @@ |Mode can be one of these: | -measure measures execution time | -compile shows compiled module without execution - | -check provides syntax check + | -check [-env=]provides syntax check | -check -cgi provides syntax check in CGI-mode | | -encoding= set output encoding @@ -184,6 +185,24 @@ КонецПроцедуры +Процедура ТестДолжен_ПроверитьЧтоМетодПрочитатьНаПустомПотокеВернетНеопределено() Экспорт + + Путь = ПутьОСкрипт(); + + Процесс = СоздатьПроцесс("""" + Путь + """",,Истина); + Процесс.Запустить(); + Процесс.ОжидатьЗавершения(); + + Стр = Процесс.ПотокВывода.Прочитать(); + юТест.ПроверитьРавенство(Тип("Строка"), ТипЗнч(Стр), "Сначала должен был прочитать строку"); + юТест.ПроверитьЛожь(ПустаяСтрока(Стр), "Вывод не должен быть пустым"); + + Стр = Процесс.ПотокВывода.Прочитать(); + юТест.ПроверитьРавенство(Тип("Неопределено"), ТипЗнч(Стр), "После должен был прочитать Неопределено"); + юТест.ПроверитьИстину(ПустаяСтрока(Стр), "Вывод должен быть пустым"); + +КонецПроцедуры + Функция ЗаписатьТестовыйСкрипт() ТекстСкрипта = " diff --git a/tests/reflector.os b/tests/reflector.os index a74a4bf47..2edf35613 100644 --- a/tests/reflector.os +++ b/tests/reflector.os @@ -21,6 +21,8 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьМетод_ПолучитьТаблицуМетодов_ДляРазныхТипов"); ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоПараметрыИзмененныеВПроцедуреВозвращеныВМассив"); + ВсеТесты.Добавить("ТестДолжен_ПроверитьМетод_ПолучитьТаблицуСвойств"); + Возврат ВсеТесты; КонецФункции @@ -179,7 +181,7 @@ ТаблицаМетодов = Рефлектор.ПолучитьТаблицуМетодов(Пример); юТест.ПроверитьРавенство(Строка(ТипЗнч(ТаблицаМетодов)), "ТаблицаЗначений", "ТаблицаМетодов"); - юТест.ПроверитьРавенство(3, ТаблицаМетодов.Количество(), "ТаблицаМетодов.Количество()"); + юТест.ПроверитьРавенство(4, ТаблицаМетодов.Количество(), "ТаблицаМетодов.Количество()"); Метод0 = ТаблицаМетодов.Найти("вызватьметод", "Имя"); юТест.ПроверитьНеРавенство(Неопределено, Метод0, "Метод0"); @@ -258,6 +260,21 @@ КонецПроцедуры +Процедура ТестДолжен_ПроверитьМетод_ПолучитьТаблицуСвойств() Экспорт + + Пример = ПолучитьОбъектДляПроверки("test_reflector"); + Рефлектор = Новый Рефлектор; + + ТаблицаСвойств = Рефлектор.ПолучитьТаблицуСвойств(Пример); + юТест.ПроверитьРавенство(3, ТаблицаСвойств.Количество()); + + юТест.ПроверитьРавенство("ЭкспортнаяПеременная", ТаблицаСвойств[1].Имя); + + ТаблицаСвойств = Рефлектор.ПолучитьТаблицуСвойств(Рефлектор); + юТест.ПроверитьРавенство(0, ТаблицаСвойств.Количество()); + +КонецПроцедуры + Функция ПолучитьОбъектДляПроверки(ИмяКласса) ТекПуть = Новый Файл(ТекущийСценарий().Источник).Путь; ПодключитьСценарий(ТекПуть+"example-test.os", ИмяКласса); diff --git a/tests/showversion.os b/tests/showversion.os index ae9f40d15..523cff81f 100644 --- a/tests/showversion.os +++ b/tests/showversion.os @@ -25,10 +25,8 @@ Процесс = СоздатьПроцесс(ПутьОСкрипт() + " -version", , Истина); Процесс.Запустить(); Процесс.ОжидатьЗавершения(); - + ДанныеВывода = Процесс.ПотокВывода.Прочитать(); - ДанныеВывода = СокрП(ДанныеВывода); - СистемнаяИнформация = Новый СистемнаяИнформация; юТест.ПроверитьРавенство(ДанныеВывода, СистемнаяИнформация.Версия, "Версия вывода не совпадает с системной информацией!"); diff --git a/tests/source-licensing.os b/tests/source-licensing.os new file mode 100644 index 000000000..b10accc39 --- /dev/null +++ b/tests/source-licensing.os @@ -0,0 +1,127 @@ +#Использовать asserts + +Перем юТест; + +Функция ПолучитьСписокТестов(ЮнитТестирование) Экспорт + + юТест = ЮнитТестирование; + + ВсеТесты = Новый Массив; + + ВсеТесты.Добавить("ТестДолжен_ПроверитьЧтоВсеФайлыИмеютПрефиксЛицензии"); + + Возврат ВсеТесты; +КонецФункции + +Процедура ТестДолжен_ПроверитьЧтоВсеФайлыИмеютПрефиксЛицензии() Экспорт + + КаталогИсходников = КаталогИсходниковПроекта(); + + Если не КаталогИсходников.Существует() Тогда + Возврат; // если запустили тесты вне каталога репы GIT, то тест не имеет смысла. + КонецЕсли; + + юТест.ПроверитьИстину(ПротестироватьИсходники(КаталогИсходников.ПолноеИмя), "Какие-то файлы не имеют лицензии. См. полный лог сборки"); + +КонецПроцедуры + +Функция КаталогИсходниковПроекта() + Возврат Новый Файл(ОбъединитьПути(ТекущийСценарий().Каталог,"../src")); +КонецФункции + +Функция ПротестироватьИсходники(Знач КаталогИсходников, Знач ИсправлятьТутЖе = Ложь) Экспорт + + ФайлыИсключения = Новый Массив; // чужой код + ФайлыИсключения.Добавить("src/GlobalAssemblyInfo.cs"); + ФайлыИсключения.Добавить("src/oscript/Web/Multipart/"); + ФайлыИсключения.Добавить("src/DebugServer/DebugSession.cs"); + ФайлыИсключения.Добавить("src/DebugServer/ServiceProxy.cs"); + + ВсеФайлы = НайтиФайлы(КаталогИсходников, ПолучитьМаскуВсеФайлы()); + ЕстьОшибки = Ложь; + + Для Каждого Файл Из ВсеФайлы Цикл + + Если Файл.Расширение = ".cs" Тогда + + ЭтоФайлИсключение = Ложь; + ПриведенныйПуть = СтрЗаменить(Файл.ПолноеИмя, "\", "/"); + Для Каждого ФайлИсключение Из ФайлыИсключения Цикл + Если Найти(ПриведенныйПуть, ФайлИсключение) > 0 Тогда + ЭтоФайлИсключение = Истина; + КонецЕсли; + КонецЦикла; + + Если ЭтоФайлИсключение Тогда + Продолжить; + КонецЕсли; + + ЕстьОшибкиСейчас = Не ПроверитьФайл(Файл); + ЕстьОшибки = ЕстьОшибки ИЛИ ЕстьОшибкиСейчас; + + Если ЕстьОшибкиСейчас и ИсправлятьТутЖе Тогда + ИсправитьФайл(Файл); + КонецЕсли; + + ИначеЕсли Файл.ЭтоКаталог() и Файл.Имя <> "obj" и Файл.Имя <> "packages" Тогда + ЕстьОшибкиСейчас = Не ПротестироватьИсходники(Файл.ПолноеИмя, ИсправлятьТутЖе); + ЕстьОшибки = ЕстьОшибки ИЛИ ЕстьОшибкиСейчас; + КонецЕсли; + + КонецЦикла; + + Возврат Не ЕстьОшибки; + +КонецФункции + +Функция ПроверитьФайл(Знач Файл) + + Префикс = ПрефиксЛицензии(); + + Документ = Новый ТекстовыйДокумент; + Документ.Прочитать(Файл.ПолноеИмя); + + СтрокаВФайле = + Документ.ПолучитьСтроку(1) + " + |" + Документ.ПолучитьСтроку(2) + " + |" + Документ.ПолучитьСтроку(3) + " + |" + Документ.ПолучитьСтроку(4) + " + |" + Документ.ПолучитьСтроку(5) + " + |" + Документ.ПолучитьСтроку(6); + + Попытка + юТест.ПроверитьРавенство(Префикс, СтрокаВФайле, "В файле " + Файл.ПолноеИмя + " должен присутствовать префикс лицензии"); + Исключение + Сообщить(ИнформацияОбОшибке().Описание); + Возврат Ложь; + КонецПопытки; + + Возврат Истина; + +КонецФункции + +Процедура ИсправитьФайл(Знач Файл) + Сообщить("ИСПРАВЛЯЮ ФАЙЛ: " + Файл.ПолноеИмя); + Документ = Новый ТекстовыйДокумент; + Документ.Прочитать(Файл.ПолноеИмя); + Документ.ВставитьСтроку(1, ПрефиксЛицензии()); + Документ.Записать(Файл.ПолноеИмя); +КонецПроцедуры + +Функция ПрефиксЛицензии() + Возврат + "/*---------------------------------------------------------- + |This Source Code Form is subject to the terms of the + |Mozilla Public License, v.2.0. If a copy of the MPL + |was not distributed with this file, You can obtain one + |at http://mozilla.org/MPL/2.0/. + |----------------------------------------------------------*/"; +КонецФункции + +Если СтартовыйСценарий().Источник = ТекущийСценарий().Источник Тогда + Если АргументыКоманднойСтроки.Количество() и АргументыКоманднойСтроки[0] = "-fix" Тогда + юТест = Утверждения; + Сообщить("Автофикс"); + ПротестироватьИсходники(КаталогИсходниковПроекта().ПолноеИмя, Истина); + КонецЕсли; +КонецЕсли; diff --git a/tests/start-all.cmd b/tests/start-all.cmd index c2f28fada..e65d33344 100644 --- a/tests/start-all.cmd +++ b/tests/start-all.cmd @@ -9,7 +9,7 @@ rem echo ᠬ rem echo �ਯ�� ���஢���� %pathdir% @echo on -"%ProgramFiles(x86)%\OneScript\oscript.exe" "%pathdir%\testrunner.os" -runall %1 %2 %3 %4 %5 +"%ProgramFiles(x86)%\OneScript\bin\oscript.exe" "%pathdir%\testrunner.os" -runall %1 %2 %3 %4 %5 @echo off rem echo ��� ������ %ERRORLEVEL% diff --git a/tests/sysinfo.os b/tests/sysinfo.os index bb42e82e0..286598cc9 100644 --- a/tests/sysinfo.os +++ b/tests/sysinfo.os @@ -20,15 +20,34 @@ ВсеТесты.Добавить("ТестДолжен_ПолучитьПеременнуюPATH"); ВсеТесты.Добавить("ТестДолжен_УстановитьПеременную"); ВсеТесты.Добавить("ТестДолжен_ПолучитьВерсиюOneScript"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПользователяОС"); + + // Значения зависят от машины запуска + ВсеТесты.Добавить("ТестДолжен_ПолучитьЭто64БитнаяОперационнаяСистема"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьКоличествоПроцессоров"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьРазмерСистемнойСтраницы"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьВремяРаботыСМоментаЗагрузки"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьИменаЛогическихДисков"); + // Пути к папкам + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_РепозиторийДокументов"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_ДанныеПриложений"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_ЛокальныйКаталогДанныхПриложений"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_РабочийСтол"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_КаталогРабочийСтол"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_МояМузыка"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_МоиРисунки"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_Шаблоны"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_МоиВидеозаписи"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_ОбщиеШаблоны"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_ПрофильПользователя"); + ВсеТесты.Добавить("ТестДолжен_ПолучитьПолучитьПутьПапки_ОбщийКаталогДанныхПриложения"); Возврат ВсеТесты; КонецФункции Процедура ТестДолжен_ПолучитьЗначенияОкружения() Экспорт - Си = Новый СистемнаяИнформация(); - - Переменные = Си.ПеременныеСреды(); + Переменные = ПеременныеСреды(); юТест.ПроверитьЛожь(Переменные.Количество() = 0); @@ -36,20 +55,18 @@ Процедура ТестДолжен_ПолучитьПеременнуюPATH() Экспорт - Си = Новый СистемнаяИнформация(); - юТест.ПроверитьЛожь(ПустаяСтрока(Си.ПолучитьПеременнуюСреды("PATH"))); + юТест.ПроверитьЛожь(ПустаяСтрока(ПолучитьПеременнуюСреды("PATH"))); КонецПроцедуры Процедура ТестДолжен_УстановитьПеременную() Экспорт - Си = Новый СистемнаяИнформация(); - СтароеЗначение = Си.ПолучитьПеременнуюСреды("OS"); + СтароеЗначение = ПолучитьПеременнуюСреды("OS"); НовоеЗначение = "NewTestValue"; - Си.УстановитьПеременнуюСреды("OS", НовоеЗначение); + УстановитьПеременнуюСреды("OS", НовоеЗначение); - юТест.ПроверитьРавенство(НовоеЗначение, Си.ПолучитьПеременнуюСреды("OS")); + юТест.ПроверитьРавенство(НовоеЗначение, ПолучитьПеременнуюСреды("OS")); КонецПроцедуры @@ -60,4 +77,98 @@ КонецПроцедуры +Процедура ТестДолжен_ПолучитьПользователяОС() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьЛожь(ПустаяСтрока(Си.ПользовательОС)); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьЭто64БитнаяОперационнаяСистема() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьИстину(Си.Это64БитнаяОперационнаяСистема); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьКоличествоПроцессоров() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьБольше(Си.КоличествоПроцессоров,0); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьРазмерСистемнойСтраницы() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьБольше(Си.РазмерСистемнойСтраницы,0); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьВремяРаботыСМоментаЗагрузки() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьБольше(Си.ВремяРаботыСМоментаЗагрузки,0); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьИменаЛогическихДисков() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьБольше(Си.ИменаЛогическихДисков.Количество(),0); +КонецПроцедуры + +/////////////////////////////////////////////////////////////////////// +// +// Проверка спец.папок +// +/////////////////////////////////////////////////////////////////////// + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_РепозиторийДокументов() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.МоиДокументы),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_ДанныеПриложений() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.ДанныеПриложений),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_ЛокальныйКаталогДанныхПриложений() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.ЛокальныйКаталогДанныхПриложений),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_РабочийСтол() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.РабочийСтол),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_КаталогРабочийСтол() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.КаталогРабочийСтол),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_МояМузыка() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.МояМузыка),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_МоиРисунки() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.МоиРисунки),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_Шаблоны() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.Шаблоны),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_МоиВидеозаписи() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.МоиВидеозаписи),""); +КонецПроцедуры +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_ОбщиеШаблоны() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.ОбщиеШаблоны),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_ПрофильПользователя() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.ПрофильПользователя),""); +КонецПроцедуры + +Процедура ТестДолжен_ПолучитьПолучитьПутьПапки_ОбщийКаталогДанныхПриложения() Экспорт + Си = Новый СистемнаяИнформация(); + юТест.ПроверитьНеРавенство(СИ.ПолучитьПутьПапки(СпециальнаяПапка.ОбщийКаталогДанныхПриложения),""); +КонецПроцедуры \ No newline at end of file diff --git a/tests/testdata/magic-object.os b/tests/testdata/magic-object.os new file mode 100644 index 000000000..ec942e602 --- /dev/null +++ b/tests/testdata/magic-object.os @@ -0,0 +1,2 @@ +Процедура ПриСозданииОбъекта(Прм1, Прм2, Прм3, Прм4 = 4) +КонецПроцедуры \ No newline at end of file diff --git a/tests/testdata/no-magic-object.os b/tests/testdata/no-magic-object.os new file mode 100644 index 000000000..be223d287 --- /dev/null +++ b/tests/testdata/no-magic-object.os @@ -0,0 +1,2 @@ +Процедура КакаяТоПроцедура(Прм1, Прм2, Прм3, Прм4 = 4) +КонецПроцедуры \ No newline at end of file diff --git a/tests/testrunner.os b/tests/testrunner.os index e4a1777f1..9bc663f40 100644 --- a/tests/testrunner.os +++ b/tests/testrunner.os @@ -239,8 +239,14 @@ КонецЕсли; КонецЕсли; ИначеЕсли КомандаЗапуска = СтруктураПараметровЗапуска.ЗапуститьКаталог Тогда - путьКТестам = МассивПараметров[НомерПараметраПутьКТестам]; - НомерОчередногоПараметра = НомерОчередногоПараметра + 1; + + Если МассивПараметров.Количество() > НомерПараметраПутьКТестам Тогда + путьКТестам = МассивПараметров[НомерПараметраПутьКТестам]; + НомерОчередногоПараметра = НомерОчередногоПараметра + 1; + Иначе + путьКТестам = ТекущийКаталог(); + КонецЕсли; + КонецЕсли; Если МассивПараметров.Количество() > НомерОчередногоПараметра и (КомандаЗапуска = СтруктураПараметровЗапуска.Запустить или КомандаЗапуска = СтруктураПараметровЗапуска.ЗапуститьКаталог ) Тогда diff --git a/tests/valuetable.os b/tests/valuetable.os index 2b1037dab..4e9c0f4c9 100644 --- a/tests/valuetable.os +++ b/tests/valuetable.os @@ -33,6 +33,10 @@ ВсеТесты.Добавить("ТестДолжен_СкопироватьТаблицуНесколькоКолонок"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСверткуБезУказанияКолонок"); + ВсеТесты.Добавить("ТестДолжен_ЗагрузитьКолонку"); + + ВсеТесты.Добавить("ТестДолжен_ПроверитьТипизациюКолонки"); + Возврат ВсеТесты; КонецФункции @@ -137,10 +141,12 @@ С1 = Т.Добавить(); С2 = Т.Добавить(); С2_5 = Т.Добавить(); + С2_6 = Т.Добавить(); С3 = Т.Добавить(); С4 = Т.Добавить(); Т.Удалить(С2_5); + Т.Удалить(2); юТест.ПроверитьРавенство(Т.Количество(), 4); @@ -281,7 +287,11 @@ КонецЦикла; + КолонкаСумма = Т.Колонки.Сумма; + юТест.ПроверитьРавенство(Т.Итог("Сумма"), мСумма); + юТест.ПроверитьРавенство(Т.Итог(2), мСумма); + юТест.ПроверитьРавенство(Т.Итог(КолонкаСумма), мСумма); Т.Свернуть("", "Сумма"); @@ -309,9 +319,18 @@ КонецЦикла; + // Передаем имя колонки юТест.ПроверитьИстину(МассивыИдентичны(Т.ВыгрузитьКолонку("Ключ"), ЭталонКлючей), "Массивы ключей должны совпадать"); юТест.ПроверитьИстину(МассивыИдентичны(Т.ВыгрузитьКолонку("Значение"), ЭталонЗначений), "Массивы значений должны совпадать"); - + + // Передаем индекс колонки + юТест.ПроверитьИстину(МассивыИдентичны(Т.ВыгрузитьКолонку(0), ЭталонКлючей), "Массивы ключей должны совпадать"); + юТест.ПроверитьИстину(МассивыИдентичны(Т.ВыгрузитьКолонку(1), ЭталонЗначений), "Массивы значений должны совпадать"); + + // Передаем колонку + юТест.ПроверитьИстину(МассивыИдентичны(Т.ВыгрузитьКолонку(Т.Колонки.Ключ), ЭталонКлючей), "Массивы ключей должны совпадать"); + юТест.ПроверитьИстину(МассивыИдентичны(Т.ВыгрузитьКолонку(Т.Колонки.Значение), ЭталонЗначений), "Массивы значений должны совпадать"); + КонецПроцедуры Функция МассивыИдентичны(Знач Проверяемый, Знач Эталон) @@ -479,3 +498,61 @@ юТест.ПроверитьРавенство(Т.Получить(1).Колонка1, "Значение2", "Свёртка по значениям"); КонецПроцедуры + +Процедура ТестДолжен_ЗагрузитьКолонку() Экспорт + + Т = Новый ТаблицаЗначений; + + Т.Колонки.Добавить("Количество1"); + Т.Колонки.Добавить("Количество2"); + Т.Колонки.Добавить("Количество3"); + + Для Инд = 1 По 5 Цикл + + НоваяСтрока = Т.Добавить(); + + КонецЦикла; + + Количество = Новый Массив; + Количество.Добавить(1); + Количество.Добавить(2); + Количество.Добавить(3); + Количество.Добавить(4); + Количество.Добавить(5); + + Т.ЗагрузитьКолонку(Количество, "Количество1"); + Т.ЗагрузитьКолонку(Количество, 1); + Т.ЗагрузитьКолонку(Количество, Т.Колонки.Количество3); + + юТест.ПроверитьРавенство(Т.Итог("Количество1"), 15); + юТест.ПроверитьРавенство(Т.Итог("Количество2"), 15); + юТест.ПроверитьРавенство(Т.Итог("Количество3"), 15); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьТипизациюКолонки() Экспорт + + Таблица = Новый ТаблицаЗначений; + Таблица.Колонки.Добавить("Колонка1", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(10))); + + СтрокаТаблицы = Таблица.Добавить(); + СтрокаТаблицы.Колонка1 = 1; + + юТест.ПроверитьРавенство(СтрокаТаблицы.Колонка1, "1"); + + СтрокаТаблицы.Колонка1 = Неопределено; + юТест.ПроверитьРавенство(СтрокаТаблицы.Колонка1, "", "Неопределено - Пустая строка"); + + Таблица.Колонки.Добавить("Колонка2", Новый ОписаниеТипов("Строка,Число")); + СтрокаТаблицы.Колонка2 = 1; + юТест.ПроверитьРавенство(СтрокаТаблицы.Колонка2, 1); + + СтрокаТаблицы.Колонка2 = "ъ"; + юТест.ПроверитьРавенство(СтрокаТаблицы.Колонка2, "ъ"); + + + СтрокаТаблицы.Колонка2 = Неопределено; + юТест.ПроверитьРавенство(СтрокаТаблицы.Колонка2, Неопределено); + +КонецПроцедуры + diff --git a/tests/valuetree.os b/tests/valuetree.os index c716465f9..d0ff974da 100644 --- a/tests/valuetree.os +++ b/tests/valuetree.os @@ -34,6 +34,10 @@ ВсеТесты.Добавить("ТестДолжен_ПроверитьВстроенныеСвойства"); ВсеТесты.Добавить("ТестДолжен_ПроверитьСортировкуСтрок"); + + ВсеТесты.Добавить("ТестДолжен_УстановитьШирину"); + + ВсеТесты.Добавить("ТестДолжен_ПроверитьТипизациюКолонки"); Возврат ВсеТесты; @@ -597,3 +601,41 @@ ПроверитьСортировку(Д, Истина, Истина); КонецПроцедуры + +Процедура ТестДолжен_УстановитьШирину() Экспорт + + Д = Новый ДеревоЗначений; + Колонка = Д.Колонки.Добавить("Ключ"); + + Колонка.Ширина = 5; + + юТест.ПроверитьРавенство(Колонка.Ширина, 5, "Установка/чтение ширины колонки"); + +КонецПроцедуры + +Процедура ТестДолжен_ПроверитьТипизациюКолонки() Экспорт + + Дерево = Новый ДеревоЗначений; + Дерево.Колонки.Добавить("Колонка1", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(10))); + + СтрокаДерева = Дерево.Строки.Добавить(); + СтрокаДерева.Колонка1 = 1; + + юТест.ПроверитьРавенство(СтрокаДерева.Колонка1, "1"); + + СтрокаДерева.Колонка1 = Неопределено; + юТест.ПроверитьРавенство(СтрокаДерева.Колонка1, "", "Неопределено - Пустая строка"); + + Дерево.Колонки.Добавить("Колонка2", Новый ОписаниеТипов("Строка,Число")); + СтрокаДерева.Колонка2 = 1; + юТест.ПроверитьРавенство(СтрокаДерева.Колонка2, 1); + + СтрокаДерева.Колонка2 = "ъ"; + юТест.ПроверитьРавенство(СтрокаДерева.Колонка2, "ъ"); + + + СтрокаДерева.Колонка2 = Неопределено; + юТест.ПроверитьРавенство(СтрокаДерева.Колонка2, Неопределено); + +КонецПроцедуры +