From 97efaa62c4ea5c35224586bc4d70e147a6149c1c Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Mon, 28 May 2018 10:11:13 -0700 Subject: [PATCH 1/3] Add .appveyor.yml This will enable us to run tests in a windows environment during CI. I am only running io/test since the formatting and binary compatibility tests are handled by travis and appveyor do not provide as many build agents as travis. --- .appveyor.yml | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 .appveyor.yml diff --git a/.appveyor.yml b/.appveyor.yml new file mode 100644 index 00000000..75db69e3 --- /dev/null +++ b/.appveyor.yml @@ -0,0 +1,28 @@ +build: off + +init: + - git config --global core.autocrlf input + +install: + - SET JAVA_HOME=C:\Program Files\Java\jdk1.8.0 + - SET PATH=%JAVA_HOME%\bin;%PATH% + + - ps: | + Add-Type -AssemblyName System.IO.Compression.FileSystem + if (!(Test-Path -Path "C:\sbt" )) { + (new-object System.Net.WebClient).DownloadFile( + 'https://github.com/sbt/sbt/releases/download/v1.1.5/sbt-1.1.5.zip', + 'C:\sbt-bin.zip' + ) + [System.IO.Compression.ZipFile]::ExtractToDirectory("C:\sbt-bin.zip", "C:\sbt") + } + - SET PATH=C:\sbt\sbt\bin;%PATH% + - SET SBT_VER=1.1.5 + - SET SBT_OPTS=-XX:MaxPermSize=2g -Xmx4g -Dfile.encoding=UTF8 -Dsbt.version=1.1.5 + - SET SCALA_VERSION=2.12.6 +test_script: + - sbt "++2.12.6 io/test" + +cache: + - '%USERPROFILE%\.ivy2\cache' + - '%USERPROFILE%\.sbt' From 87e9e49bb8faf829c5f3a0f9c69e5cb865309a6c Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Mon, 28 May 2018 11:36:06 -0700 Subject: [PATCH 2/3] Treat ERROR_ACCESS_DENIED as file not found After adding the .appveyor.yml, I found that my builds would typically fail and usually one of the polling watch service threads died with an IOException with message "CreateFile() failed with error 5." I tracked this down to ERROR_ACCESS_DENIED, which seemed weird since any of the files that were being polled were generated by the test. It turns out that windows will return ERROR_ACCESS_DENIED when the file was in a pending delete state. https://stackoverflow.com/questions/6680491/why-does-windows-return-error-access-denied-when-i-try-to-open-a-delete-pended-f While this feels slightly wrong, it doesn't seem completely unreasonable to consider ERROR_ACCESS_DENIED to be like a FileNotFoundException. In either the deleted or privileged file cases, the file is effectively not findable. An alternative would be to throw a different exception and catch that in getModifiedTimeOrZero. Bonus: remove unused import --- io/src/main/scala/sbt/internal/io/Milli.scala | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/io/src/main/scala/sbt/internal/io/Milli.scala b/io/src/main/scala/sbt/internal/io/Milli.scala index 47e041e7..22e094f1 100644 --- a/io/src/main/scala/sbt/internal/io/Milli.scala +++ b/io/src/main/scala/sbt/internal/io/Milli.scala @@ -17,7 +17,6 @@ import com.sun.jna.{ Native => JNANative } import com.sun.jna.Platform import com.sun.jna.platform.win32.Kernel32 -import com.sun.jna.platform.win32.WinNT.GENERIC_READ import com.sun.jna.platform.win32.WinNT.FILE_SHARE_READ import com.sun.jna.platform.win32.WinNT.FILE_SHARE_WRITE import com.sun.jna.platform.win32.WinNT.FILE_SHARE_DELETE @@ -30,6 +29,7 @@ import com.sun.jna.platform.win32.WinBase.INVALID_HANDLE_VALUE import com.sun.jna.platform.win32.WinBase.FILETIME import com.sun.jna.platform.win32.WinError.ERROR_FILE_NOT_FOUND import com.sun.jna.platform.win32.WinError.ERROR_PATH_NOT_FOUND +import com.sun.jna.platform.win32.WinError.ERROR_ACCESS_DENIED import sbt.io.JavaMilli import sbt.internal.io.MacJNA._ @@ -285,6 +285,8 @@ private object WinMilli extends MilliNative[FILETIME] { val err = GetLastError() if (err == ERROR_FILE_NOT_FOUND || err == ERROR_PATH_NOT_FOUND) throw new FileNotFoundException("Not found: " + lpFileName) + else if (err == ERROR_ACCESS_DENIED) + throw new FileNotFoundException("Access denied: " + lpFileName) else throw new IOException("CreateFile() failed with error " + GetLastError()) } From e081631bd4f64f90e25edd99e48f005340f76a8f Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Mon, 28 May 2018 12:09:02 -0700 Subject: [PATCH 3/3] Bump timeout I was seeing transient failures of this test on windows, which has significantly slower file access apis than linux and osx. --- .../scala/sbt/internal/io/SourceModificationWatchSpec.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/io/src/test/scala/sbt/internal/io/SourceModificationWatchSpec.scala b/io/src/test/scala/sbt/internal/io/SourceModificationWatchSpec.scala index c61841ed..fe5537ed 100644 --- a/io/src/test/scala/sbt/internal/io/SourceModificationWatchSpec.scala +++ b/io/src/test/scala/sbt/internal/io/SourceModificationWatchSpec.scala @@ -360,8 +360,10 @@ abstract class SourceModificationWatchSpec( // Longer timeout because there are many file system operations. This can be very expensive // especially in the PollingWatchSpec since both the PollingWatchService and the EventMonitor // overflow handler are hammering the file system. To minimize the conflicts, we set a long - // interval between polls in the PollingWatchService using getServiceWithPollDelay. - val deadline = 20.seconds.fromNow + // interval between polls in the PollingWatchService using getServiceWithPollDelay. The + // timeout was increased from 20.seconds to 40.seconds to address transient failures of + // this test on Appveyor windows builds. + val deadline = 40.seconds.fromNow val monitor = defaultMonitor(getServiceWithPollDelay(1.second), parentDir, tc = () => deadline.isOverdue) try {