From 0785686612f79fb4047296c3b4a008d909e52c1d Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Fri, 26 Apr 2019 20:56:25 +0200 Subject: [PATCH 01/17] setup ftp and sftp servers on docker with respective keys --- docker-compose.yml | 26 ++++++++++ ftp/src/test/resources/ftpd/pure-ftpd.pem | 48 +++++++++++++++++ ftp/src/test/resources/sftpd/init.sh | 6 +++ .../test/resources/sftpd/ssh_host_ed25519_key | 7 +++ .../resources/sftpd/ssh_host_ed25519_key.pub | 1 + ftp/src/test/resources/sftpd/ssh_host_rsa_key | 51 +++++++++++++++++++ .../test/resources/sftpd/ssh_host_rsa_key.pub | 1 + 7 files changed, 140 insertions(+) create mode 100644 ftp/src/test/resources/ftpd/pure-ftpd.pem create mode 100644 ftp/src/test/resources/sftpd/init.sh create mode 100644 ftp/src/test/resources/sftpd/ssh_host_ed25519_key create mode 100644 ftp/src/test/resources/sftpd/ssh_host_ed25519_key.pub create mode 100644 ftp/src/test/resources/sftpd/ssh_host_rsa_key create mode 100644 ftp/src/test/resources/sftpd/ssh_host_rsa_key.pub diff --git a/docker-compose.yml b/docker-compose.yml index d10c2061f7..e85c78f6e6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -66,6 +66,21 @@ services: image: deangiberson/aws-dynamodb-local ports: - "8001:8000" + ftp: + image: stilliard/pure-ftpd:latest + ports: + - "21000:21" + - "30000-30009:30000-30009" + volumes: + - ./ftp/target/home:/home/username/ + - ./ftp/target/passwd:/etc/pure-ftpd/passwd + - ./ftp/src/test/resources/ftpd/:/etc/ssl/private/ + environment: + PUBLICHOST: "localhost" + FTP_USER_NAME: username + FTP_USER_PASS: userpass + FTP_USER_HOME: /home/username + ADDED_FLAGS: "--tls=1" geode: container_name: geode image: apachegeode/geode:1.8.0 @@ -199,3 +214,14 @@ services: environment: - "ORIENTDB_ROOT_PASSWORD=root" command: /orientdb/bin/server.sh -Dmemory.chunk.size=268435456 + sftp: + image: atmoz/sftp + volumes: + - ./ftp/target/home:/home/username/upload + - ./ftp/src/test/resources/id_rsa.pub:/home/username/.ssh/keys/id_rsa.pub:ro + - ./ftp/src/test/resources/sftpd/ssh_host_ed25519_key:/tmp/ssh_host_ed25519_key + - ./ftp/src/test/resources/sftpd/ssh_host_rsa_key:/tmp/ssh_host_rsa_key + - ./ftp/src/test/resources/sftpd/init.sh:/etc/sftp.d/init.sh + ports: + - "2222:22" + command: username:userpass \ No newline at end of file diff --git a/ftp/src/test/resources/ftpd/pure-ftpd.pem b/ftp/src/test/resources/ftpd/pure-ftpd.pem new file mode 100644 index 0000000000..956a69ee49 --- /dev/null +++ b/ftp/src/test/resources/ftpd/pure-ftpd.pem @@ -0,0 +1,48 @@ +-----BEGIN PRIVATE KEY----- +MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQCx/i/7dZ5rKFUD +PsFb3/xtZF5qSftKj14vPGrTTb85guP1VjAzmFuZE4jFWsr4edJMzOzy5NvBrE5t +zrefRKbqUc5cwfPT9v1xawn/pj9h7+JMo3VUdqL0eVm8IF0q3dp+KQOrZrcRhsIz +1JsOqXJmEKagj0X62VYv39jeIWTndDG6h7+54Q5GMzyd/LorEkM69XrnFEtfCF5w +BVe+mz2UIAO+xDtxbwBTzkOcGDCYEiXTManlJvDCKciQPsfLF0VwmxIkb+xgZ2zB +2Ckao20twD/LKjZzqlJODde8FMAIQNbgpM8DdZUp5kFhmHj2redw5fdarOr7XE6X +HizOejcBAgMBAAECggEAX5mnK+iArg17m8KZGD+11QuTqoMR9XoLnFNXDSc1Di6/ +QYaJXSz4Bb/4NggN/GdyDM4EdnF1lxB1D4V4GpNFE5XcwPVrgO2oMsLLHASvBmtR +oNgqrLML00NabzDy2ZNPR3PABM+mhENdC3mlzro0N5254YMSkykooY4ZbTWCfM2F +VlqoloLrwwCQGXMCBmMZUKKmofEac03KmG8ouNSSqsEfMtoGfL+M7La1n/lQ51UF +wK2HgLi4flU34TLUXrGxYC7F1y1+tmm4hZG2WCxJS6uvJ+GekERnIXyWhbIQuMUW +sOBft3A75BPNFt/1r8ew2nhvjcjRaohIWQscmf6gAQKBgQDtFf1djsA7HNJGpKUg +ahUlYIt+cucEEesfovufENBOhpNTqWn0JLFVpJorqehSsWvF3taxr8Hf7DyVvlFv +MO+VD8TSme+xrASHpNwd7rpc2n5QM02IKxgsTh3xCO8sAk7yxfJ9Ue4s6H/6tFsy +2WC935HHHhgigaZKA/pD2ALCGQKBgQDAMVcw8CoeDoaGE2KSWsjBUSJeoZ5pA77F ++F7kJAmvwYlbdUka6nxuyMbtbLnAVwOacae1xxSXasW0wGULNZKgbD1NdhztpLt0 +mEFtE+uc83Q+HNwrIMDBpsaIqU9OW+U2GOZUUCIHwjdfgDpjygEOUqhc4ALecZyD +ZsfTSDBJKQKBgQCs5Tlk7gJv2V/bVpx5HAOZw2NW7pJcHHkcFC5tXMScT3XHMCft +fIi6TRSFPR4ImAxhO1XUNLktBElWZnlanhRJ3zsI3mu3ZRvUk7xWM89CgbBV6mPj +JpI1VS5upbZNoM1ULFjfXU1VAKS7/qT3WyE6tnzH+cFeALB1D5uFuFSimQKBgQCY +VsPA46zOtD7HCZiJX3JfYRs4HS0+GhzeONemSDZxXJuupdGzhwfonDapvROjNJWD +lvETceCNgLGDazjsYKN/iywwOR4G9Bst+P1rI24Psx2Bmkid2tFO7g3SBzn4Z3jQ +n336eKXwtm5DwZUGwfiCTNxs+ZbskOs5cH+VplO3uQKBgQCkVfpt6eufT85ArjwY +EzNI4T/6DXc/b/v6d+7Tk7LafxPIjBkM8bnKPSHqsBA3HJ7630xLg880YSN0ew6d +tTeCIFFRodYcslFNfnNOqkA2x4q4pEmjAk+ChHg+s9jvarBAHFLTSPgkcMiQru11 +TXpsVPrNzl+eQObY/dNouIvuYw== +-----END PRIVATE KEY----- +-----BEGIN CERTIFICATE----- +MIIDQDCCAiigAwIBAgIJAI/KIXjP2G2BMA0GCSqGSIb3DQEBCwUAMDUxEjAQBgNV +BAMMCWxvY2FsaG9zdDESMBAGA1UECgwJbG9jYWxob3N0MQswCQYDVQQGEwJVUzAe +Fw0xOTA0MjUwNjM2NTZaFw0yNDA0MjQwNjM2NTZaMDUxEjAQBgNVBAMMCWxvY2Fs +aG9zdDESMBAGA1UECgwJbG9jYWxob3N0MQswCQYDVQQGEwJVUzCCASIwDQYJKoZI +hvcNAQEBBQADggEPADCCAQoCggEBALH+L/t1nmsoVQM+wVvf/G1kXmpJ+0qPXi88 +atNNvzmC4/VWMDOYW5kTiMVayvh50kzM7PLk28GsTm3Ot59EpupRzlzB89P2/XFr +Cf+mP2Hv4kyjdVR2ovR5WbwgXSrd2n4pA6tmtxGGwjPUmw6pcmYQpqCPRfrZVi/f +2N4hZOd0MbqHv7nhDkYzPJ38uisSQzr1eucUS18IXnAFV76bPZQgA77EO3FvAFPO +Q5wYMJgSJdMxqeUm8MIpyJA+x8sXRXCbEiRv7GBnbMHYKRqjbS3AP8sqNnOqUk4N +17wUwAhA1uCkzwN1lSnmQWGYePat53Dl91qs6vtcTpceLM56NwECAwEAAaNTMFEw +HQYDVR0OBBYEFP/3oItwaZDztL0GoWiM1YMcyb8WMB8GA1UdIwQYMBaAFP/3oItw +aZDztL0GoWiM1YMcyb8WMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQAD +ggEBADO6cRZPsqAj/6JZSw177TPlGSq90G2PRdMW+ET0ljqO1c8AHOId7y9nGTgJ +xEeAaR2ZZ6wLQShRFNF73KGo4vc+jbp/WcxhUCWEDoK4AMKqch6XDjtxid9UH1wj +wgm2LB223hMzBU4Ub7c3G8b1wpksRYQyNjv/i6DsJIJf+B+p3OoxdVUmbeyen0gA +rnyEo7IsJLTjf2aWpNIqkL7y9GZeTTPKx4k6uIn+RB3d7u6AFXQ7FdH6Bqu3vslg +NrOoUSnl1pa5Np1DMzJj/oiJ/8vLN/dVYzl9QDZ3heIHdEROvt1/5anLmhfO0AEH +X24nJrGi6nZbhh6A/6Kcg9W2Ehg= +-----END CERTIFICATE----- diff --git a/ftp/src/test/resources/sftpd/init.sh b/ftp/src/test/resources/sftpd/init.sh new file mode 100644 index 0000000000..7df0aee5f6 --- /dev/null +++ b/ftp/src/test/resources/sftpd/init.sh @@ -0,0 +1,6 @@ +#!/bin/bash + +cp /tmp/ssh_host_ed25519_key /etc/ssh/ +cp /tmp/ssh_host_rsa_key /etc/ssh/ +chmod 600 /etc/ssh/ssh_host_ed25519_key +chmod 600 /etc/ssh/ssh_host_rsa_key \ No newline at end of file diff --git a/ftp/src/test/resources/sftpd/ssh_host_ed25519_key b/ftp/src/test/resources/sftpd/ssh_host_ed25519_key new file mode 100644 index 0000000000..afa4a3972b --- /dev/null +++ b/ftp/src/test/resources/sftpd/ssh_host_ed25519_key @@ -0,0 +1,7 @@ +-----BEGIN OPENSSH PRIVATE KEY----- +b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW +QyNTUxOQAAACDSqTT3yzQ9nnLc9C/1YT9pxCRGTUHxi73mTMn4DX3iAwAAAJDmJjzk5iY8 +5AAAAAtzc2gtZWQyNTUxOQAAACDSqTT3yzQ9nnLc9C/1YT9pxCRGTUHxi73mTMn4DX3iAw +AAAEDQwMfbEQP+RBWwOBC2i7zP0N4yOQl4joztgIxunTRmGdKpNPfLND2ectz0L/VhP2nE +JEZNQfGLveZMyfgNfeIDAAAAC3RnYW1iZXRATVNJAQI= +-----END OPENSSH PRIVATE KEY----- diff --git a/ftp/src/test/resources/sftpd/ssh_host_ed25519_key.pub b/ftp/src/test/resources/sftpd/ssh_host_ed25519_key.pub new file mode 100644 index 0000000000..b9e47d2277 --- /dev/null +++ b/ftp/src/test/resources/sftpd/ssh_host_ed25519_key.pub @@ -0,0 +1 @@ +ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINKpNPfLND2ectz0L/VhP2nEJEZNQfGLveZMyfgNfeID user@localhost diff --git a/ftp/src/test/resources/sftpd/ssh_host_rsa_key b/ftp/src/test/resources/sftpd/ssh_host_rsa_key new file mode 100644 index 0000000000..a4180b59e9 --- /dev/null +++ b/ftp/src/test/resources/sftpd/ssh_host_rsa_key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +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 +-----END RSA PRIVATE KEY----- diff --git a/ftp/src/test/resources/sftpd/ssh_host_rsa_key.pub b/ftp/src/test/resources/sftpd/ssh_host_rsa_key.pub new file mode 100644 index 0000000000..dafb0b3025 --- /dev/null +++ b/ftp/src/test/resources/sftpd/ssh_host_rsa_key.pub @@ -0,0 +1 @@ +ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5BMmhCrvnvJSO5gJUqV3ULQl/V1M3HaXhlXjBUahRy5ZrPtJqnn2V/uylLBELK30P0Uz4AoBg/1+vIJnNVdf3rS/Y6HCpJLDIHqM5DF41vZocyCMUr8C5buJ6vS6LcL3L2iylMOHjFKWj6I/ec09cxsJ5GfBLoszoNKQHoAxFzx2fn+L+0j33eTx4Jzkb0SjfJ+ImmnkB2F3He29DVa1psF6BGTSEXeauXfv/kM7JPs3zjMzKQouSKYh3ha5bP4g3ZuFzXpTF118977zta/xAFKrCeYDf8DZ3Y7lj67vkGH/TSfJcbhaI8erNCqePn1Z2zYa+aVB+s5+FQUiIL/zqV8r5Xz6FqCHmJYX9klLuTcKoq+WM35uqKYR3vOCzOlqrrzNUFTxkL5auGI9IlPoRq/k1QT5mfz8htpk40QJYmATX56xGwq1U+PJ5SR6xuA+DayWOWjqVc3HnvmdJYYSFYNbb6K9aqGLGRbcWM8vWE6MSQRUzRlo6m0jNfBzwjmoarodKjs6CvZwdEZ1yd/GWQbuPqnaH8OabvT4wYL0lSGU8cxUW4vtCbJ0lGkH0mRSXXbgDYAXcuaSv5rm8WsrA7JExmdwKXgU7rgvjcYwpmUk3H42yN/qHTYrPzvAdkJY77oWHgZGLTD+kps+CWy5ergugouyXbqBxjqUYH+OVcQ== user@localhost From c746becfcd0282506429ac7275e9b055c5f16292 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Fri, 26 Apr 2019 21:46:57 +0200 Subject: [PATCH 02/17] moved tests to docker, refactoring --- .../stream/alpakka/ftp/BaseFtpSupport.java | 18 ++ .../stream/alpakka/ftp/BaseSftpSupport.java | 45 +++++ .../akka/stream/alpakka/ftp/BaseSupport.java | 23 +++ .../stream/alpakka/ftp/BaseSupportImpl.java | 129 ++++++++++++++ ...FtpStageTest.java => CommonStageTest.java} | 26 +-- .../stream/alpakka/ftp/FtpBaseSupport.java | 162 ------------------ .../akka/stream/alpakka/ftp/FtpStageTest.java | 25 ++- .../akka/stream/alpakka/ftp/FtpSupport.java | 26 --- .../stream/alpakka/ftp/FtpSupportImpl.java | 44 ----- .../stream/alpakka/ftp/FtpsStageTest.java | 29 ++-- .../stream/alpakka/ftp/FtpsSupportImpl.java | 82 --------- .../alpakka/ftp/KeyFileSftpSourceTest.java | 32 ++-- .../alpakka/ftp/PlainFtpSupportImpl.java | 49 ------ .../alpakka/ftp/RawKeySftpSourceTest.java | 34 ++-- .../stream/alpakka/ftp/SftpStageTest.java | 30 ++-- .../stream/alpakka/ftp/SftpSupportImpl.java | 112 ------------ .../ftp/StrictHostCheckingSftpSourceTest.java | 35 ++-- .../java/docs/javadsl/FtpWritingTest.java | 14 +- ftp/src/test/resources/hostkey.pem | 15 -- ftp/src/test/resources/known_hosts | 2 +- ftp/src/test/resources/server.jks | Bin 3877 -> 0 bytes ftp/src/test/resources/users.properties | 3 - .../akka/stream/alpakka/ftp/BaseFtpSpec.scala | 9 +- .../stream/alpakka/ftp/BaseFtpsSpec.scala | 9 +- .../stream/alpakka/ftp/BaseSftpSpec.scala | 21 ++- .../akka/stream/alpakka/ftp/BaseSpec.scala | 14 +- .../alpakka/ftp/CommonFtpStageSpec.scala | 125 +++++++------- .../scala/docs/scaladsl/FtpExamplesSpec.scala | 29 ++-- 28 files changed, 420 insertions(+), 722 deletions(-) create mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java create mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java create mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupport.java create mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java rename ftp/src/test/java/akka/stream/alpakka/ftp/{CommonFtpStageTest.java => CommonStageTest.java} (83%) delete mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/FtpBaseSupport.java delete mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupport.java delete mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupportImpl.java delete mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/FtpsSupportImpl.java delete mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/PlainFtpSupportImpl.java delete mode 100644 ftp/src/test/java/akka/stream/alpakka/ftp/SftpSupportImpl.java delete mode 100644 ftp/src/test/resources/hostkey.pem delete mode 100644 ftp/src/test/resources/server.jks delete mode 100644 ftp/src/test/resources/users.properties diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java new file mode 100644 index 0000000000..1f91e9e154 --- /dev/null +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java @@ -0,0 +1,18 @@ +package akka.stream.alpakka.ftp; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class BaseFtpSupport extends BaseSupportImpl { + + private final Path ROOT_DIR = Paths.get("ftp/target/home"); + public final String HOSTNAME = "localhost"; + public final int PORT = 21000; + public final FtpCredentials CREDENTIALS = FtpCredentials.create("username", "userpass"); + + @Override + public Path getRootDir() { + return ROOT_DIR; + } + +} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java new file mode 100644 index 0000000000..9478ec6eec --- /dev/null +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016-2019 Lightbend Inc. + */ + +package akka.stream.alpakka.ftp; + +import java.io.File; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class BaseSftpSupport extends BaseSupportImpl { + + private final Path ROOT_DIR = Paths.get("ftp/target/home"); + final String HOSTNAME = "localhost"; + final int PORT = 2222; + final FtpCredentials CREDENTIALS = FtpCredentials.create("username", "userpass"); + // Issue: the root folder of the sftp server is not writable so tests must happen inside a sub-folder + final String ROOT_PATH = "upload/"; + + public static final byte[] CLIENT_PRIVATE_KEY_PASSPHRASE = + "secret".getBytes(Charset.forName("UTF-8")); + + private File clientPrivateKeyFile; + private File knownHostsFile; + + BaseSftpSupport() { + clientPrivateKeyFile = new File(getClass().getResource("/id_rsa").getPath()); + knownHostsFile = new File(getClass().getResource("/known_hosts").getPath()); + } + + public File getClientPrivateKeyFile() { + return clientPrivateKeyFile; + } + + public File getKnownHostsFile() { + return knownHostsFile; + } + + @Override + public Path getRootDir() { + return ROOT_DIR; + } + +} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupport.java new file mode 100644 index 0000000000..b6fc5b9655 --- /dev/null +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupport.java @@ -0,0 +1,23 @@ +/* + * Copyright (C) 2016-2019 Lightbend Inc. + */ + +package akka.stream.alpakka.ftp; + +interface BaseSupport { + + void cleanFiles(); + + void generateFiles(int numFiles, int pageSize, String basePath); + + void putFileOnFtp(String filePath); + + void putFileOnFtpWithContents(String filePath, byte[] fileContents); + + byte[] getFtpFileContents(String filePath); + + boolean fileExists(String filePath); + + String getDefaultContent(); + +} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java new file mode 100644 index 0000000000..2d97caad12 --- /dev/null +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2016-2019 Lightbend Inc. + */ + +package akka.stream.alpakka.ftp; + +import akka.actor.ActorSystem; +import akka.stream.ActorMaterializer; +import akka.stream.Materializer; +import org.junit.After; + +import java.io.File; +import java.io.IOException; +import java.nio.file.*; +import java.nio.file.attribute.BasicFileAttributes; + +public abstract class BaseSupportImpl implements BaseSupport, AkkaSupport { + + private ActorSystem system = ActorSystem.create("alpakka-ftp"); + private Materializer materializer = ActorMaterializer.create(system); + + private String loremIpsum = + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent auctor imperdiet " + + "velit, eu dapibus nisl dapibus vitae. Sed quam lacus, fringilla posuere ligula at, " + + "aliquet laoreet nulla. Aliquam id fermentum justo. Aliquam et massa consequat, " + + "pellentesque dolor nec, gravida libero. Phasellus elit eros, finibus eget " + + "sollicitudin ac, consectetur sed ante. Etiam ornare lacus blandit nisi gravida " + + "accumsan. Sed in lorem arcu. Vivamus et eleifend ligula. Maecenas ut commodo ante. " + + "Suspendisse sit amet placerat arcu, porttitor sagittis velit. Quisque gravida mi a " + + "porttitor ornare. Cras lorem nisl, sollicitudin vitae odio at, vehicula maximus " + + "mauris. Sed ac purus ac turpis pellentesque cursus ac eget est. Pellentesque " + + "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."; + + abstract Path getRootDir(); + + @Override @After + public void cleanFiles() { + try { + Files.walkFileTree( + getRootDir(), + new SimpleFileVisitor() { + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) + throws IOException { + if (!dir.equals(getRootDir())) Files.delete(dir); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.deleteIfExists(file); + return FileVisitResult.CONTINUE; + } + }); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + @Override + public void generateFiles(int numFiles, int pageSize, String basePath) { + String path = basePath.endsWith("/") ? basePath.substring(0, basePath.length() - 1) : basePath; + int i = 1; + while (i <= numFiles) { + int j = i / pageSize; + String subDir = (j > 0) ? "dir_" + j + "/" : ""; + putFileOnFtp(path + "/" + subDir + "sample_" + i); + i++; + } + } + + @Override + public void putFileOnFtp(String filePath) { + putFileOnFtpWithContents(filePath, getDefaultContent().getBytes()); + } + + @Override + public void putFileOnFtpWithContents(String filePath, byte[] fileContents) { + String relativePath = filePath.startsWith("/") ? filePath.substring(1) : filePath; + try { + File parent = getRootDir().resolve(relativePath).getParent().toFile(); + if (!parent.exists()) { + parent.mkdirs(); + } + Path path = getRootDir().resolve(relativePath); + Files.write(path, fileContents); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + @Override + public byte[] getFtpFileContents(String filePath) { + String relativePath = filePath.startsWith("/") ? filePath.substring(1) : filePath; + try { + Path path = getRootDir().resolve(relativePath); + return Files.readAllBytes(path); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + @Override + public boolean fileExists(String filePath) { + String relativePath = filePath.startsWith("/") ? filePath.substring(1) : filePath; + try { + return getRootDir().resolve(relativePath).toFile().exists(); + } catch (Throwable t) { + throw new RuntimeException(t); + } + } + + @Override + public String getDefaultContent() { + return loremIpsum; + } + + @Override + public ActorSystem getSystem() { + return system; + } + + @Override + public Materializer getMaterializer() { + return materializer; + } + +} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java similarity index 83% rename from ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java rename to ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java index 93479b13b6..76bebbe5c7 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java @@ -24,7 +24,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -interface CommonFtpStageTest extends FtpSupport, AkkaSupport { +interface CommonStageTest extends BaseSupport, AkkaSupport { Source getBrowserSource(String basePath) throws Exception; @@ -60,18 +60,18 @@ default void listFiles() throws Exception { default void fromPath() throws Exception { String fileName = "sample_io"; - putFileOnFtp(FtpBaseSupport.FTP_ROOT_DIR, fileName); + putFileOnFtp(fileName); final ActorSystem system = getSystem(); final Materializer materializer = getMaterializer(); - Source> source = getIOSource("/" + fileName); + Source> source = getIOSource(fileName); Pair, TestSubscriber.Probe> pairResult = source.toMat(TestSink.probe(system), Keep.both()).run(materializer); TestSubscriber.Probe probe = pairResult.second(); probe.request(100).expectNextOrComplete(); - int expectedNumOfBytes = getLoremIpsum().getBytes().length; + int expectedNumOfBytes = getDefaultContent().getBytes().length; IOResult result = pairResult.first().toCompletableFuture().get(3, TimeUnit.SECONDS); assertEquals(IOResult.createSuccessful(expectedNumOfBytes), result); @@ -82,24 +82,24 @@ default void toPath() throws Exception { final Materializer materializer = getMaterializer(); - final ByteString fileContent = ByteString.fromString(getLoremIpsum()); + final ByteString fileContent = ByteString.fromString(getDefaultContent()); Sink> sink = getIOSink("/" + fileName); CompletionStage resultCompletionStage = Source.single(fileContent).runWith(sink, materializer); - int expectedNumOfBytes = getLoremIpsum().getBytes().length; + int expectedNumOfBytes = getDefaultContent().getBytes().length; IOResult result = resultCompletionStage.toCompletableFuture().get(3, TimeUnit.SECONDS); - byte[] actualStoredContent = getFtpFileContents(FtpBaseSupport.FTP_ROOT_DIR, fileName); + byte[] actualStoredContent = getFtpFileContents(fileName); assertEquals(IOResult.createSuccessful(expectedNumOfBytes), result); - Assert.assertArrayEquals(actualStoredContent, getLoremIpsum().getBytes()); + Assert.assertArrayEquals(actualStoredContent, getDefaultContent().getBytes()); } default void remove() throws Exception { final String fileName = "sample_io"; - putFileOnFtp(FtpBaseSupport.FTP_ROOT_DIR, fileName); + putFileOnFtp(fileName); final Materializer materializer = getMaterializer(); Source source = getBrowserSource("/"); @@ -108,7 +108,7 @@ default void remove() throws Exception { IOResult result = resultCompletionStage.toCompletableFuture().get(3, TimeUnit.SECONDS); - Boolean fileExists = fileExists(FtpBaseSupport.FTP_ROOT_DIR, fileName); + Boolean fileExists = fileExists(fileName); assertEquals(IOResult.createSuccessful(1), result); assertFalse(fileExists); @@ -117,7 +117,7 @@ default void remove() throws Exception { default void move() throws Exception { final String fileName = "sample_io"; final String fileName2 = "sample_io2"; - putFileOnFtp(FtpBaseSupport.FTP_ROOT_DIR, fileName); + putFileOnFtp(fileName); final Materializer materializer = getMaterializer(); Source source = getBrowserSource("/"); @@ -128,8 +128,8 @@ default void move() throws Exception { assertEquals(IOResult.createSuccessful(1), result); - assertFalse(fileExists(FtpBaseSupport.FTP_ROOT_DIR, fileName)); + assertFalse(fileExists(fileName)); - assertTrue(fileExists(FtpBaseSupport.FTP_ROOT_DIR, fileName2)); + assertTrue(fileExists(fileName2)); } } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpBaseSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpBaseSupport.java deleted file mode 100644 index d0e0365b39..0000000000 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpBaseSupport.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package akka.stream.alpakka.ftp; - -import akka.actor.ActorSystem; -import akka.stream.ActorMaterializer; -import akka.stream.Materializer; -import org.apache.mina.util.AvailablePortFinder; - -import java.io.File; -import java.io.IOException; -import java.nio.file.*; -import java.nio.file.attribute.BasicFileAttributes; - -public abstract class FtpBaseSupport implements FtpSupport, AkkaSupport { - - private static final int BASE_PORT = 21000; - private static final int DEFAULT_NUM_FILES = 30; - public static final String hostname = "localhost"; - public static final String FTP_ROOT_DIR = "/home"; - - private File usersFile; - private FileSystem fileSystem; - private ActorSystem system; - private Materializer materializer; - - private Integer port; - - private String loremIpsum = - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent auctor imperdiet " - + "velit, eu dapibus nisl dapibus vitae. Sed quam lacus, fringilla posuere ligula at, " - + "aliquet laoreet nulla. Aliquam id fermentum justo. Aliquam et massa consequat, " - + "pellentesque dolor nec, gravida libero. Phasellus elit eros, finibus eget " - + "sollicitudin ac, consectetur sed ante. Etiam ornare lacus blandit nisi gravida " - + "accumsan. Sed in lorem arcu. Vivamus et eleifend ligula. Maecenas ut commodo ante. " - + "Suspendisse sit amet placerat arcu, porttitor sagittis velit. Quisque gravida mi a " - + "porttitor ornare. Cras lorem nisl, sollicitudin vitae odio at, vehicula maximus " - + "mauris. Sed ac purus ac turpis pellentesque cursus ac eget est. Pellentesque " - + "habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas."; - - FtpBaseSupport() { - try { - usersFile = new File(getClass().getClassLoader().getResource("users.properties").getFile()); - port = AvailablePortFinder.getNextAvailable(BASE_PORT); - system = ActorSystem.create("alpakka-ftp"); - materializer = ActorMaterializer.create(system); - } finally { - port = BASE_PORT; - } - } - - public void cleanFiles() { - for (Path rootDir : getFileSystem().getRootDirectories()) { - try { - Files.walkFileTree( - rootDir, - new SimpleFileVisitor() { - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) - throws IOException { - if (dir != rootDir && !dir.toString().equals(FTP_ROOT_DIR)) Files.delete(dir); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - Files.deleteIfExists(file); - return FileVisitResult.CONTINUE; - } - }); - } catch (Throwable t) { - t.printStackTrace(); - } - } - } - - public void generateFiles(int numFiles, int pageSize, String basePath) { - String base = ""; - if (!basePath.isEmpty()) { - if ('/' != basePath.charAt(0)) { - base = "/" + basePath; - } else { - base = basePath; - } - } - int i = 1; - while (i <= numFiles) { - int j = i / pageSize; - String subDir = (j > 0) ? "/dir_" + j : ""; - putFileOnFtp(FTP_ROOT_DIR + base + subDir, "sample_" + i); - i++; - } - } - - public void putFileOnFtp(String path, String fileName) { - putFileOnFtpWithContents(path, fileName, loremIpsum.getBytes()); - } - - public void putFileOnFtpWithContents(String path, String fileName, byte[] fileContents) { - try { - Path baseDir = getFileSystem().getPath(path); - if (!Files.exists(baseDir)) { - Files.createDirectories(baseDir); - } - Path filePath = baseDir.resolve(fileName); - Files.write(filePath, fileContents); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - public byte[] getFtpFileContents(String path, String fileName) { - try { - Path baseDir = getFileSystem().getPath(path); - Path filePath = baseDir.resolve(fileName); - return Files.readAllBytes(filePath); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - public boolean fileExists(String path, String fileName) { - try { - Path baseDir = getFileSystem().getPath(path); - Path filePath = baseDir.resolve(fileName); - return Files.exists(filePath); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - public ActorSystem getSystem() { - return system; - } - - public Materializer getMaterializer() { - return materializer; - } - - protected File getUsersFile() { - return usersFile; - } - - protected FileSystem getFileSystem() { - return fileSystem; - } - - protected void setFileSystem(FileSystem fileSystem) { - this.fileSystem = fileSystem; - } - - protected Integer getPort() { - return port; - } - - public String getLoremIpsum() { - return loremIpsum; - } -} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java index cd273fb0de..538a5ab38d 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java @@ -15,31 +15,31 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class FtpStageTest extends PlainFtpSupportImpl implements CommonFtpStageTest { +public class FtpStageTest extends BaseFtpSupport implements CommonStageTest { @Test public void listFiles() throws Exception { - CommonFtpStageTest.super.listFiles(); + CommonStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonFtpStageTest.super.fromPath(); + CommonStageTest.super.fromPath(); } @Test public void toPath() throws Exception { - CommonFtpStageTest.super.toPath(); + CommonStageTest.super.toPath(); } @Test public void remove() throws Exception { - CommonFtpStageTest.super.remove(); + CommonStageTest.super.remove(); } @Test public void move() throws Exception { - CommonFtpStageTest.super.move(); + CommonStageTest.super.move(); } public Source getBrowserSource(String basePath) throws Exception { @@ -64,12 +64,11 @@ public Sink> getMoveSink( } private FtpSettings settings() throws Exception { - final FtpSettings settings = - FtpSettings.create(InetAddress.getByName("localhost")) - .withPort(getPort()) - .withCredentials(FtpCredentials.anonymous()) - .withBinary(false) - .withPassiveMode(true); - return settings; + return FtpSettings.create(InetAddress.getByName(HOSTNAME)) + .withPort(PORT) + .withCredentials(CREDENTIALS) + .withBinary(false) + .withPassiveMode(true); } + } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupport.java deleted file mode 100644 index 7f4af14896..0000000000 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupport.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package akka.stream.alpakka.ftp; - -interface FtpSupport { - - void startServer(); - - void stopServer(); - - void cleanFiles(); - - void generateFiles(int numFiles, int pageSize, String basePath); - - void putFileOnFtp(String path, String fileName); - - void putFileOnFtpWithContents(String path, String fileName, byte[] fileContents); - - byte[] getFtpFileContents(String path, String fileName); - - boolean fileExists(String path, String fileName); - - String getLoremIpsum(); -} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupportImpl.java deleted file mode 100644 index 1480a1c217..0000000000 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpSupportImpl.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package akka.stream.alpakka.ftp; - -import org.apache.ftpserver.FtpServer; -import org.apache.ftpserver.FtpServerFactory; -import org.junit.After; -import org.junit.Before; - -import java.nio.file.FileSystem; - -abstract class FtpSupportImpl extends FtpBaseSupport { - - private FtpServer ftpServer; - - @Before - public void startServer() { - try { - FtpServerFactory factory = createFtpServerFactory(getPort()); - ftpServer = factory.createServer(); - ftpServer.start(); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - @After - public void stopServer() { - try { - ftpServer.stop(); - ftpServer = null; - FileSystem fileSystem = getFileSystem(); - if (fileSystem.isOpen()) { - fileSystem.close(); - } - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - protected abstract FtpServerFactory createFtpServerFactory(Integer port); -} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java index 7f66ba0710..300270fb40 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java @@ -15,36 +15,31 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class FtpsStageTest extends FtpsSupportImpl implements CommonFtpStageTest { - - public FtpsStageTest() { - setAuthValue("TLS"); - setUseImplicit(false); - } +public class FtpsStageTest extends BaseFtpSupport implements CommonStageTest { @Test public void listFiles() throws Exception { - CommonFtpStageTest.super.listFiles(); + CommonStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonFtpStageTest.super.fromPath(); + CommonStageTest.super.fromPath(); } @Test public void toPath() throws Exception { - CommonFtpStageTest.super.toPath(); + CommonStageTest.super.toPath(); } @Test public void remove() throws Exception { - CommonFtpStageTest.super.remove(); + CommonStageTest.super.remove(); } @Test public void move() throws Exception { - CommonFtpStageTest.super.move(); + CommonStageTest.super.move(); } public Source getBrowserSource(String basePath) throws Exception { @@ -69,12 +64,10 @@ public Sink> getMoveSink( } private FtpsSettings settings() throws Exception { - final FtpsSettings settings = - FtpsSettings.create(InetAddress.getByName("localhost")) - .withPort(getPort()) - .withCredentials(FtpCredentials.anonymous()) - .withBinary(false) - .withPassiveMode(false); - return settings; + return FtpsSettings.create(InetAddress.getByName(HOSTNAME)) + .withPort(PORT) + .withCredentials(CREDENTIALS) + .withBinary(false) + .withPassiveMode(true); } } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsSupportImpl.java deleted file mode 100644 index 3f604bfe8e..0000000000 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsSupportImpl.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package akka.stream.alpakka.ftp; - -import org.apache.ftpserver.FtpServerFactory; -import org.apache.ftpserver.listener.ListenerFactory; -import org.apache.ftpserver.ssl.SslConfigurationFactory; - -import java.io.File; - -abstract class FtpsSupportImpl extends PlainFtpSupportImpl { - - static final String AUTH_VALUE_SSL = "SSL"; - static final String AUTH_VALUE_TLS = "TLS"; - private static final String FTP_SERVER_KEY_STORE_PASSWORD = "password"; - - private String clientAuth = "none"; - private String authValue; - private Boolean useImplicit; - - private File ftpServerKeyStore; - - protected FtpsSupportImpl() { - ftpServerKeyStore = new File(getClass().getClassLoader().getResource("server.jks").getFile()); - } - - @Override - protected FtpServerFactory createFtpServerFactory(Integer port) { - FtpServerFactory factory = super.createFtpServerFactory(port); - ListenerFactory listenerFactory = new ListenerFactory(factory.getListener(DEFAULT_LISTENER)); - listenerFactory.setImplicitSsl(getUseImplicit()); - listenerFactory.setSslConfiguration(sslConfigFactory().createSslConfiguration()); - factory.addListener(DEFAULT_LISTENER, listenerFactory.createListener()); - return factory; - } - - private SslConfigurationFactory sslConfigFactory() { - SslConfigurationFactory factory = new SslConfigurationFactory(); - factory.setSslProtocol(getAuthValue()); - - factory.setKeystoreFile(ftpServerKeyStore); - factory.setKeystoreType("JKS"); - factory.setKeystoreAlgorithm("SunX509"); - factory.setKeyPassword(FTP_SERVER_KEY_STORE_PASSWORD); - factory.setKeystorePassword(FTP_SERVER_KEY_STORE_PASSWORD); - - factory.setClientAuthentication(getClientAuth()); - - factory.setTruststoreFile(ftpServerKeyStore); - factory.setTruststoreType("JKS"); - factory.setTruststoreAlgorithm("SunX509"); - factory.setTruststorePassword(FTP_SERVER_KEY_STORE_PASSWORD); - - return factory; - } - - String getClientAuth() { - return clientAuth; - } - - void setClientAuth(String clientAuth) { - this.clientAuth = clientAuth; - } - - String getAuthValue() { - return authValue; - } - - void setAuthValue(String authValue) { - this.authValue = authValue; - } - - Boolean getUseImplicit() { - return useImplicit; - } - - void setUseImplicit(Boolean useImplicit) { - this.useImplicit = useImplicit; - } -} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java index efaf220d40..45579a461a 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java @@ -15,28 +15,28 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class KeyFileSftpSourceTest extends SftpSupportImpl implements CommonFtpStageTest { +public class KeyFileSftpSourceTest extends BaseSftpSupport implements CommonStageTest { @Test public void listFiles() throws Exception { - CommonFtpStageTest.super.listFiles(); + CommonStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonFtpStageTest.super.fromPath(); + CommonStageTest.super.fromPath(); } public Source getBrowserSource(String basePath) throws Exception { - return Sftp.ls(basePath, settings()); + return Sftp.ls(ROOT_PATH + basePath, settings()); } public Source> getIOSource(String path) throws Exception { - return Sftp.fromPath(path, settings()); + return Sftp.fromPath(ROOT_PATH + path, settings()); } public Sink> getIOSink(String path) throws Exception { - return Sftp.toPath(path, settings()); + return Sftp.toPath(ROOT_PATH + path, settings()); } public Sink> getRemoveSink() throws Exception { @@ -45,19 +45,17 @@ public Sink> getRemoveSink() throws Exception public Sink> getMoveSink( Function destinationPath) throws Exception { - return Sftp.move(destinationPath, settings()); + return Sftp.move(f -> ROOT_PATH + destinationPath.apply(f), settings()); } private SftpSettings settings() throws Exception { - final SftpSettings settings = - SftpSettings.create(InetAddress.getByName("localhost")) - .withPort(getPort()) - .withCredentials( - FtpCredentials.create("different user and password", "will fail password auth")) - .withStrictHostKeyChecking(false) // strictHostKeyChecking - .withSftpIdentity( - SftpIdentity.createFileSftpIdentity( - getClientPrivateKeyFile().getPath(), CLIENT_PRIVATE_KEY_PASSPHRASE)); - return settings; + return SftpSettings.create(InetAddress.getByName(HOSTNAME)) + .withPort(PORT) + .withCredentials( + FtpCredentials.create("username", "wrong password")) + .withStrictHostKeyChecking(false) // strictHostKeyChecking + .withSftpIdentity( + SftpIdentity.createFileSftpIdentity( + getClientPrivateKeyFile().getPath(), CLIENT_PRIVATE_KEY_PASSPHRASE)); } } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/PlainFtpSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/PlainFtpSupportImpl.java deleted file mode 100644 index 83f7326a9e..0000000000 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/PlainFtpSupportImpl.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package akka.stream.alpakka.ftp; - -import com.google.common.jimfs.Configuration; -import com.google.common.jimfs.Jimfs; -import org.apache.ftpserver.ConnectionConfigFactory; -import org.apache.ftpserver.FtpServerFactory; -import org.apache.ftpserver.filesystem.jimfs.JimfsFactory; -import org.apache.ftpserver.ftplet.UserManager; -import org.apache.ftpserver.listener.ListenerFactory; -import org.apache.ftpserver.usermanager.ClearTextPasswordEncryptor; -import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory; - -public abstract class PlainFtpSupportImpl extends FtpSupportImpl { - - private static final int MAX_LOGINS = 1000; - static final String DEFAULT_LISTENER = "default"; - - protected FtpServerFactory createFtpServerFactory(Integer port) { - Configuration fsConfig = - Configuration.unix().toBuilder().setAttributeViews("basic", "posix").build(); - setFileSystem(Jimfs.newFileSystem(fsConfig)); - JimfsFactory fsf = new JimfsFactory(getFileSystem()); - fsf.setCreateHome(true); - - PropertiesUserManagerFactory pumf = new PropertiesUserManagerFactory(); - pumf.setAdminName("admin"); - pumf.setPasswordEncryptor(new ClearTextPasswordEncryptor()); - pumf.setFile(getUsersFile()); - UserManager userMgr = pumf.createUserManager(); - - ListenerFactory factory = new ListenerFactory(); - factory.setPort(port); - - FtpServerFactory serverFactory = new FtpServerFactory(); - serverFactory.setUserManager(userMgr); - serverFactory.setFileSystem(fsf); - ConnectionConfigFactory configFactory = new ConnectionConfigFactory(); - configFactory.setMaxLogins(MAX_LOGINS); - configFactory.setMaxAnonymousLogins(MAX_LOGINS); - serverFactory.setConnectionConfig(configFactory.createConnectionConfig()); - serverFactory.addListener(DEFAULT_LISTENER, factory.createListener()); - - return serverFactory; - } -} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java index 9ef0a05c0b..ff1e16e150 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java @@ -17,28 +17,28 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class RawKeySftpSourceTest extends SftpSupportImpl implements CommonFtpStageTest { +public class RawKeySftpSourceTest extends BaseSftpSupport implements CommonStageTest { @Test public void listFiles() throws Exception { - CommonFtpStageTest.super.listFiles(); + CommonStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonFtpStageTest.super.fromPath(); + CommonStageTest.super.fromPath(); } public Source getBrowserSource(String basePath) throws Exception { - return Sftp.ls(basePath, settings()); + return Sftp.ls(ROOT_PATH + basePath, settings()); } public Source> getIOSource(String path) throws Exception { - return Sftp.fromPath(path, settings()); + return Sftp.fromPath(ROOT_PATH + path, settings()); } public Sink> getIOSink(String path) throws Exception { - return Sftp.toPath(path, settings()); + return Sftp.toPath(ROOT_PATH + path, settings()); } public Sink> getRemoveSink() throws Exception { @@ -47,20 +47,18 @@ public Sink> getRemoveSink() throws Exception public Sink> getMoveSink( Function destinationPath) throws Exception { - return Sftp.move(destinationPath, settings()); + return Sftp.move(f -> ROOT_PATH + destinationPath.apply(f), settings()); } private SftpSettings settings() throws Exception { - final SftpSettings settings = - SftpSettings.create(InetAddress.getByName("localhost")) - .withPort(getPort()) - .withCredentials( - FtpCredentials.create("different user and password", "will fail password auth")) - .withStrictHostKeyChecking(false) // strictHostKeyChecking - .withSftpIdentity( - SftpIdentity.createRawSftpIdentity( - Files.readAllBytes(Paths.get(getClientPrivateKeyFile().getPath())), - CLIENT_PRIVATE_KEY_PASSPHRASE)); - return settings; + return SftpSettings.create(InetAddress.getByName(HOSTNAME)) + .withPort(PORT) + .withCredentials( + FtpCredentials.create("username", "wrong password")) + .withStrictHostKeyChecking(false) // strictHostKeyChecking + .withSftpIdentity( + SftpIdentity.createRawSftpIdentity( + Files.readAllBytes(Paths.get(getClientPrivateKeyFile().getPath())), + CLIENT_PRIVATE_KEY_PASSPHRASE)); } } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java index 6ab237cc4d..2666b38ad9 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java @@ -16,43 +16,43 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class SftpStageTest extends SftpSupportImpl implements CommonFtpStageTest { +public class SftpStageTest extends BaseSftpSupport implements CommonStageTest { @Test public void listFiles() throws Exception { - CommonFtpStageTest.super.listFiles(); + CommonStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonFtpStageTest.super.fromPath(); + CommonStageTest.super.fromPath(); } @Test public void toPath() throws Exception { - CommonFtpStageTest.super.toPath(); + CommonStageTest.super.toPath(); } @Test public void remove() throws Exception { - CommonFtpStageTest.super.remove(); + CommonStageTest.super.remove(); } @Test public void move() throws Exception { - CommonFtpStageTest.super.move(); + CommonStageTest.super.move(); } public Source getBrowserSource(String basePath) throws Exception { - return Sftp.ls(basePath, settings()); + return Sftp.ls(ROOT_PATH + basePath, settings()); } public Source> getIOSource(String path) throws Exception { - return Sftp.fromPath(path, settings()); + return Sftp.fromPath(ROOT_PATH + path, settings()); } public Sink> getIOSink(String path) throws Exception { - return Sftp.toPath(path, settings()); + return Sftp.toPath(ROOT_PATH + path, settings()); } public Sink> getRemoveSink() throws Exception { @@ -61,15 +61,13 @@ public Sink> getRemoveSink() throws Exception public Sink> getMoveSink( Function destinationPath) throws Exception { - return Sftp.move(destinationPath, settings()); + return Sftp.move(f -> ROOT_PATH + destinationPath.apply(f), settings()); } private SftpSettings settings() throws Exception { - final SftpSettings settings = - SftpSettings.create(InetAddress.getByName("localhost")) - .withPort(getPort()) - .withCredentials(FtpCredentials.anonymous()) - .withStrictHostKeyChecking(false); - return settings; + return SftpSettings.create(InetAddress.getByName(HOSTNAME)) + .withPort(PORT) + .withCredentials(CREDENTIALS) + .withStrictHostKeyChecking(false); } } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/SftpSupportImpl.java deleted file mode 100644 index 7b20a7b5a3..0000000000 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpSupportImpl.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package akka.stream.alpakka.ftp; - -import com.google.common.jimfs.Configuration; -import com.google.common.jimfs.Jimfs; -import org.apache.sshd.common.NamedFactory; -import org.apache.sshd.common.file.virtualfs.VirtualFileSystemFactory; -import org.apache.sshd.common.keyprovider.FileKeyPairProvider; -import org.apache.sshd.server.command.Command; -import org.apache.sshd.server.SshServer; -import org.apache.sshd.server.auth.password.PasswordAuthenticator; -import org.apache.sshd.server.auth.password.PasswordChangeRequiredException; -import org.apache.sshd.server.auth.pubkey.PublickeyAuthenticator; -import org.apache.sshd.server.scp.ScpCommandFactory; -import org.apache.sshd.server.session.ServerSession; -import org.apache.sshd.server.subsystem.sftp.SftpSubsystemFactory; -import org.junit.After; -import org.junit.Before; -import java.io.File; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.security.PublicKey; -import java.util.Arrays; - -abstract class SftpSupportImpl extends FtpBaseSupport { - - public static final byte[] CLIENT_PRIVATE_KEY_PASSPHRASE = - "secret".getBytes(Charset.forName("UTF-8")); - - private SshServer sshd; - private File keyPairProviderFile; - private File clientPrivateKeyFile; - private File knownHostsFile; - - protected SftpSupportImpl() { - keyPairProviderFile = new File(getClass().getResource("/hostkey.pem").getPath()); - clientPrivateKeyFile = new File(getClass().getResource("/id_rsa").getPath()); - knownHostsFile = new File(getClass().getResource("/known_hosts").getPath()); - } - - @Before - public void startServer() { - try { - sshd = SshServer.setUpDefaultServer(); - sshd.setHost("127.0.0.1"); - sshd.setPort(getPort()); - sshd.setKeyPairProvider( - new FileKeyPairProvider(Paths.get(keyPairProviderFile.getAbsolutePath()))); - sshd.setSubsystemFactories(Arrays.>asList(new SftpSubsystemFactory())); - sshd.setCommandFactory(new ScpCommandFactory()); - PasswordAuthenticator passwordAuthenticator = - new PasswordAuthenticator() { - public boolean authenticate(String username, String password, ServerSession session) - throws PasswordChangeRequiredException { - return (username != null && username.equals(password)); - } - }; - sshd.setPasswordAuthenticator(passwordAuthenticator); - PublickeyAuthenticator publickeyAuthenticator = - new PublickeyAuthenticator() { - @Override - public boolean authenticate(String username, PublicKey key, ServerSession session) { - return true; - } - }; - sshd.setPublickeyAuthenticator(publickeyAuthenticator); - - // setting the virtual filesystem. - // posix attribute view is necessary in order to - // avoid jimfs relying to `toFile` method in RootedPath - // (throws UnsupportedOperationException) - Configuration fsConfig = - Configuration.unix().toBuilder().setAttributeViews("basic", "posix").build(); - setFileSystem(Jimfs.newFileSystem(fsConfig)); - Path home = getFileSystem().getPath(FTP_ROOT_DIR); - sshd.setFileSystemFactory(new VirtualFileSystemFactory(home)); - - // start - sshd.start(); - - // create home dir - if (!Files.exists(home)) { - Files.createDirectories(home); - } - - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - @After - public void stopServer() { - try { - sshd.stop(true); - } catch (Throwable t) { - throw new RuntimeException(t); - } - } - - public File getClientPrivateKeyFile() { - return clientPrivateKeyFile; - } - - public File getKnownHostsFile() { - return knownHostsFile; - } -} diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java index ffa95070f5..d83eac4d24 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java @@ -15,29 +15,28 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class StrictHostCheckingSftpSourceTest extends SftpSupportImpl - implements CommonFtpStageTest { +public class StrictHostCheckingSftpSourceTest extends BaseSftpSupport implements CommonStageTest { @Test public void listFiles() throws Exception { - CommonFtpStageTest.super.listFiles(); + CommonStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonFtpStageTest.super.fromPath(); + CommonStageTest.super.fromPath(); } public Source getBrowserSource(String basePath) throws Exception { - return Sftp.ls(basePath, settings()); + return Sftp.ls(ROOT_PATH + basePath, settings()); } public Source> getIOSource(String path) throws Exception { - return Sftp.fromPath(path, settings()); + return Sftp.fromPath(ROOT_PATH + path, settings()); } public Sink> getIOSink(String path) throws Exception { - return Sftp.toPath(path, settings()); + return Sftp.toPath(ROOT_PATH + path, settings()); } public Sink> getRemoveSink() throws Exception { @@ -46,20 +45,18 @@ public Sink> getRemoveSink() throws Exception public Sink> getMoveSink( Function destinationPath) throws Exception { - return Sftp.move(destinationPath, settings()); + return Sftp.move(f -> ROOT_PATH + destinationPath.apply(f), settings()); } private SftpSettings settings() throws Exception { - final SftpSettings settings = - SftpSettings.create(InetAddress.getByName("localhost")) - .withPort(getPort()) - .withCredentials( - FtpCredentials.create("different user and password", "will fail password auth")) - .withStrictHostKeyChecking(true) // strictHostKeyChecking - .withKnownHosts(getKnownHostsFile().getPath()) - .withSftpIdentity( - SftpIdentity.createFileSftpIdentity( - getClientPrivateKeyFile().getPath(), CLIENT_PRIVATE_KEY_PASSPHRASE)); - return settings; + return SftpSettings.create(InetAddress.getByName(HOSTNAME)) + .withPort(PORT) + .withCredentials( + FtpCredentials.create("username", "wrong password")) + .withStrictHostKeyChecking(true) // strictHostKeyChecking + .withKnownHosts(getKnownHostsFile().getPath()) + .withSftpIdentity( + SftpIdentity.createFileSftpIdentity( + getClientPrivateKeyFile().getPath(), CLIENT_PRIVATE_KEY_PASSPHRASE)); } } diff --git a/ftp/src/test/java/docs/javadsl/FtpWritingTest.java b/ftp/src/test/java/docs/javadsl/FtpWritingTest.java index 2a53b88506..712c3abf47 100644 --- a/ftp/src/test/java/docs/javadsl/FtpWritingTest.java +++ b/ftp/src/test/java/docs/javadsl/FtpWritingTest.java @@ -15,8 +15,7 @@ import java.io.PrintWriter; import java.net.InetAddress; import akka.stream.alpakka.ftp.FtpSettings; -import akka.stream.alpakka.ftp.PlainFtpSupportImpl; -import akka.stream.alpakka.ftp.FtpBaseSupport; +import akka.stream.alpakka.ftp.BaseFtpSupport; import akka.stream.Materializer; import akka.stream.javadsl.Source; import akka.testkit.javadsl.TestKit; @@ -30,7 +29,7 @@ import static org.hamcrest.CoreMatchers.is; -public class FtpWritingTest extends PlainFtpSupportImpl { +public class FtpWritingTest extends BaseFtpSupport { @After public void afterEach() { @@ -41,8 +40,9 @@ public void afterEach() { FtpSettings ftpSettings() throws Exception { // #create-settings FtpSettings ftpSettings = - FtpSettings.create(InetAddress.getByName(hostname)) - .withPort(getPort()) + FtpSettings.create(InetAddress.getByName(HOSTNAME)) + .withPort(PORT) + .withCredentials(CREDENTIALS) .withBinary(true) .withPassiveMode(true) // only useful for debugging @@ -68,7 +68,7 @@ public void targetFileShouldBeCreated() throws Exception { IOResult ioResult = result.toCompletableFuture().get(5, TimeUnit.SECONDS); assertThat(ioResult, is(IOResult.createSuccessful(25))); - assertTrue(fileExists(FtpBaseSupport.FTP_ROOT_DIR, "file.txt")); + assertTrue(fileExists("file.txt")); } @Test @@ -86,6 +86,6 @@ public void gZippedTargetFileShouldBeCreated() throws Exception { IOResult ioResult = result.toCompletableFuture().get(5, TimeUnit.SECONDS); assertThat(ioResult, is(IOResult.createSuccessful(50))); - assertTrue(fileExists(FtpBaseSupport.FTP_ROOT_DIR, "file.txt.gz")); + assertTrue(fileExists("file.txt.gz")); } } diff --git a/ftp/src/test/resources/hostkey.pem b/ftp/src/test/resources/hostkey.pem deleted file mode 100644 index 9b215f45bb..0000000000 --- a/ftp/src/test/resources/hostkey.pem +++ /dev/null @@ -1,15 +0,0 @@ ------BEGIN RSA PRIVATE KEY----- -MIICXAIBAAKBgQDdfIWeSV4o68dRrKSzFd/Bk51E65UTmmSrmW0O1ohtzi6HzsDP -jXgCtlTt3FqTcfFfI92IlTr4JWqC9UK1QT1ZTeng0MkPQmv68hDANHbt5CpETZHj -W5q4OOgWhVvj5IyOC2NZHtKlJBkdsMAa15ouOOJLzBvAvbqOR/yUROsEiQIDAQAB -AoGBANG3JDW6NoP8rF/zXoeLgLCj+tfVUPSczhGFVrQkAk4mWfyRkhN0WlwHFOec -K89MpkV1ij/XPVzU4MNbQ2yod1KiDylzvweYv+EaEhASCmYNs6LS03punml42SL9 -97tOmWfVJXxlQoLiY6jHPU97vTc65k8gL+gmmrpchsW0aqmZAkEA/c8zfmKvY37T -cxcLLwzwsqqH7g2KZGTf9aRmx2ebdW+QKviJJhbdluDgl1TNNFj5vCLznFDRHiqJ -wq0wkZ39cwJBAN9l5v3kdXj21UrurNPdlV0n2GZBt2vblooQC37XHF97r2zM7Ou+ -Lg6MyfJClyguhWL9dxnGbf3btQ0l3KDstxMCQCRaiEqjAfIjWVATzeNIXDWLHXso -b1kf5cA+cwY+vdKdTy4IeUR+Y/DXdvPWDqpf0C11aCVMohdLCn5a5ikFUycCQDhV -K/BuAallJNfmY7JxN87r00fF3ojWMJnT/fIYMFFrkQrwifXQWTDWE76BSDibsosJ -u1TGksnm8zrDh2UVC/0CQFrHTiSl/3DHvWAbOJawGKg46cnlDcAhSyV8Frs8/dlP -7YGG3eqkw++lsghqmFO6mRUTKsBmiiB2wgLGhL5pyYY= ------END RSA PRIVATE KEY----- \ No newline at end of file diff --git a/ftp/src/test/resources/known_hosts b/ftp/src/test/resources/known_hosts index 33fdc6a136..a9e359693e 100644 --- a/ftp/src/test/resources/known_hosts +++ b/ftp/src/test/resources/known_hosts @@ -1 +1 @@ -[127.0.0.1]:21000 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDdfIWeSV4o68dRrKSzFd/Bk51E65UTmmSrmW0O1ohtzi6HzsDPjXgCtlTt3FqTcfFfI92IlTr4JWqC9UK1QT1ZTeng0MkPQmv68hDANHbt5CpETZHjW5q4OOgWhVvj5IyOC2NZHtKlJBkdsMAa15ouOOJLzBvAvbqOR/yUROsEiQ== +[127.0.0.1]:2222 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC5BMmhCrvnvJSO5gJUqV3ULQl/V1M3HaXhlXjBUahRy5ZrPtJqnn2V/uylLBELK30P0Uz4AoBg/1+vIJnNVdf3rS/Y6HCpJLDIHqM5DF41vZocyCMUr8C5buJ6vS6LcL3L2iylMOHjFKWj6I/ec09cxsJ5GfBLoszoNKQHoAxFzx2fn+L+0j33eTx4Jzkb0SjfJ+ImmnkB2F3He29DVa1psF6BGTSEXeauXfv/kM7JPs3zjMzKQouSKYh3ha5bP4g3ZuFzXpTF118977zta/xAFKrCeYDf8DZ3Y7lj67vkGH/TSfJcbhaI8erNCqePn1Z2zYa+aVB+s5+FQUiIL/zqV8r5Xz6FqCHmJYX9klLuTcKoq+WM35uqKYR3vOCzOlqrrzNUFTxkL5auGI9IlPoRq/k1QT5mfz8htpk40QJYmATX56xGwq1U+PJ5SR6xuA+DayWOWjqVc3HnvmdJYYSFYNbb6K9aqGLGRbcWM8vWE6MSQRUzRlo6m0jNfBzwjmoarodKjs6CvZwdEZ1yd/GWQbuPqnaH8OabvT4wYL0lSGU8cxUW4vtCbJ0lGkH0mRSXXbgDYAXcuaSv5rm8WsrA7JExmdwKXgU7rgvjcYwpmUk3H42yN/qHTYrPzvAdkJY77oWHgZGLTD+kps+CWy5ergugouyXbqBxjqUYH+OVcQ== diff --git a/ftp/src/test/resources/server.jks b/ftp/src/test/resources/server.jks deleted file mode 100644 index 498cd764456c2dc23aba2af432268ac65d030fc6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3877 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 C@)Q67 diff --git a/ftp/src/test/resources/users.properties b/ftp/src/test/resources/users.properties deleted file mode 100644 index 8a956ac365..0000000000 --- a/ftp/src/test/resources/users.properties +++ /dev/null @@ -1,3 +0,0 @@ -ftpserver.user.anonymous -ftpserver.user.anonymous.homedirectory=/home -ftpserver.user.anonymous.writepermission=true \ No newline at end of file diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpSpec.scala index 57b0147b0e..2d6c47c9ff 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpSpec.scala @@ -12,11 +12,12 @@ import akka.util.ByteString import scala.concurrent.Future import java.net.InetAddress -trait BaseFtpSpec extends PlainFtpSupportImpl with BaseSpec { +trait BaseFtpSpec extends BaseFtpSupport with BaseSpec { val settings = FtpSettings( - InetAddress.getByName("localhost") - ).withPort(getPort) + InetAddress.getByName(HOSTNAME) + ).withPort(PORT) + .withCredentials(CREDENTIALS) .withBinary(true) .withPassiveMode(true) @@ -28,7 +29,7 @@ trait BaseFtpSpec extends PlainFtpSupportImpl with BaseSpec { emitTraversedDirectories: Boolean = false): Source[FtpFile, NotUsed] = Ftp.ls(basePath, settings, branchSelector, emitTraversedDirectories) - protected def retrieveFromPath(path: String): Source[ByteString, Future[IOResult]] = + protected def retrieveFromPath(path: String, fromRoot: Boolean = false): Source[ByteString, Future[IOResult]] = Ftp.fromPath(path, settings) protected def storeToPath(path: String, append: Boolean): Sink[ByteString, Future[IOResult]] = diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpsSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpsSpec.scala index d820f931fd..ac92872c37 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpsSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseFtpsSpec.scala @@ -13,11 +13,12 @@ import akka.util.ByteString import scala.concurrent.Future -trait BaseFtpsSpec extends FtpsSupportImpl with BaseSpec { +trait BaseFtpsSpec extends BaseFtpSupport with BaseSpec { val settings = FtpsSettings( - InetAddress.getByName("localhost") - ).withPort(getPort) + InetAddress.getByName(HOSTNAME) + ).withPort(PORT) + .withCredentials(CREDENTIALS) .withBinary(true) .withPassiveMode(true) @@ -29,7 +30,7 @@ trait BaseFtpsSpec extends FtpsSupportImpl with BaseSpec { emitTraversedDirectories: Boolean): Source[FtpFile, NotUsed] = Ftps.ls(basePath, settings, branchSelector, emitTraversedDirectories) - protected def retrieveFromPath(path: String): Source[ByteString, Future[IOResult]] = + protected def retrieveFromPath(path: String, fromRoot: Boolean = false): Source[ByteString, Future[IOResult]] = Ftps.fromPath(path, settings) protected def storeToPath(path: String, append: Boolean): Sink[ByteString, Future[IOResult]] = diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala index 5cc8590016..18090eb994 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala @@ -13,30 +13,33 @@ import akka.util.ByteString import scala.concurrent.Future -trait BaseSftpSpec extends SftpSupportImpl with BaseSpec { +trait BaseSftpSpec extends BaseSftpSupport with BaseSpec { val settings = SftpSettings( - InetAddress.getByName("localhost") - ).withPort(getPort) + InetAddress.getByName(HOSTNAME) + ).withPort(PORT) + .withCredentials(FtpCredentials.create("username", "userpass")) .withStrictHostKeyChecking(false) protected def listFiles(basePath: String): Source[FtpFile, NotUsed] = - Sftp.ls(basePath, settings) + Sftp.ls(ROOT_PATH + basePath, settings) protected def listFilesWithFilter(basePath: String, branchSelector: FtpFile => Boolean, emitTraversedDirectories: Boolean): Source[FtpFile, NotUsed] = - Sftp.ls(basePath, settings, branchSelector, emitTraversedDirectories) + Sftp.ls(ROOT_PATH + basePath, settings, branchSelector, emitTraversedDirectories) - protected def retrieveFromPath(path: String): Source[ByteString, Future[IOResult]] = - Sftp.fromPath(path, settings) + protected def retrieveFromPath(path: String, fromRoot: Boolean = false): Source[ByteString, Future[IOResult]] = { + val finalPath = if (fromRoot) path else ROOT_PATH + path + Sftp.fromPath(finalPath, settings) + } protected def storeToPath(path: String, append: Boolean): Sink[ByteString, Future[IOResult]] = - Sftp.toPath(path, settings, append) + Sftp.toPath(ROOT_PATH + path, settings, append) protected def remove(): Sink[FtpFile, Future[IOResult]] = Sftp.remove(settings) protected def move(destinationPath: FtpFile => String): Sink[FtpFile, Future[IOResult]] = - Sftp.move(destinationPath, settings) + Sftp.move(file => ROOT_PATH + destinationPath(file), settings) } diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala index 612d5ec50e..fe4fe8e084 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala @@ -23,7 +23,7 @@ trait BaseSpec with IntegrationPatience with Inside with AkkaSupport - with FtpSupport { + with BaseSupport { protected def listFiles(basePath: String): Source[FtpFile, NotUsed] @@ -31,7 +31,7 @@ trait BaseSpec branchSelector: FtpFile => Boolean, emitTraversedDirectories: Boolean = false): Source[FtpFile, NotUsed] - protected def retrieveFromPath(path: String): Source[ByteString, Future[IOResult]] + protected def retrieveFromPath(path: String, fromRoot: Boolean = false): Source[ByteString, Future[IOResult]] protected def storeToPath(path: String, append: Boolean): Sink[ByteString, Future[IOResult]] @@ -39,10 +39,6 @@ trait BaseSpec protected def move(destinationPath: FtpFile => String): Sink[FtpFile, Future[IOResult]] - protected def startServer(): Unit - - protected def stopServer(): Unit - /** For a few tests `assertAllStagesStopped` failed on Travis, this hook allows to inject a bit more patience * for the check. * @@ -54,13 +50,7 @@ trait BaseSpec cleanFiles() } - override protected def beforeAll() = { - super.beforeAll() - startServer() - } - override protected def afterAll() = { - stopServer() Await.ready(getSystem.terminate(), 42.seconds) super.afterAll() } diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala index b8cc9729ae..6fb5272630 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala @@ -4,34 +4,31 @@ package akka.stream.alpakka.ftp +import java.net.InetAddress +import java.nio.file.attribute.PosixFilePermission +import java.nio.file.{Files, Paths} + import akka.stream.IOResult -import akka.stream.alpakka.ftp.SftpSupportImpl.{CLIENT_PRIVATE_KEY_PASSPHRASE => ClientPrivateKeyPassphrase} +import BaseSftpSupport.{CLIENT_PRIVATE_KEY_PASSPHRASE => ClientPrivateKeyPassphrase} import akka.stream.scaladsl.{Keep, Sink, Source} +import akka.stream.testkit.scaladsl.StreamTestKit.assertAllStagesStopped import akka.stream.testkit.scaladsl.TestSink import akka.util.ByteString +import org.scalatest.concurrent.Eventually import org.scalatest.time.{Millis, Seconds, Span} import scala.concurrent.duration._ import scala.util.Random -import java.nio.file.attribute.PosixFilePermission -import java.nio.file.{Files, Paths} -import java.net.InetAddress - -import akka.stream.testkit.scaladsl.StreamTestKit.assertAllStagesStopped -import org.scalatest.concurrent.Eventually final class FtpStageSpec extends BaseFtpSpec with CommonFtpStageSpec +final class FtpsStageSpec extends BaseFtpsSpec with CommonFtpStageSpec final class SftpStageSpec extends BaseSftpSpec with CommonFtpStageSpec -final class FtpsStageSpec extends BaseFtpsSpec with CommonFtpStageSpec { - setAuthValue("TLS") - setUseImplicit(false) -} final class RawKeySftpSourceSpec extends BaseSftpSpec with CommonFtpStageSpec { override val settings = SftpSettings( - InetAddress.getByName("localhost") - ).withPort(getPort) - .withCredentials(FtpCredentials.create("different user and password", "will fail password auth")) + InetAddress.getByName(HOSTNAME) + ).withPort(PORT) + .withCredentials(FtpCredentials.create("username", "wrong password")) .withStrictHostKeyChecking(false) .withSftpIdentity( SftpIdentity.createRawSftpIdentity( @@ -45,9 +42,9 @@ final class KeyFileSftpSourceSpec extends BaseSftpSpec with CommonFtpStageSpec { override protected def extraWaitForStageShutdown(): Unit = Thread.sleep(10 * 1000) override val settings = SftpSettings( - InetAddress.getByName("localhost") - ).withPort(getPort) - .withCredentials(FtpCredentials.create("different user and password", "will fail password auth")) + InetAddress.getByName(HOSTNAME) + ).withPort(PORT) + .withCredentials(FtpCredentials.create("username", "wrong password")) .withStrictHostKeyChecking(false) .withSftpIdentity( SftpIdentity.createFileSftpIdentity(getClientPrivateKeyFile.getPath, ClientPrivateKeyPassphrase) @@ -56,9 +53,9 @@ final class KeyFileSftpSourceSpec extends BaseSftpSpec with CommonFtpStageSpec { final class StrictHostCheckingSftpSourceSpec extends BaseSftpSpec with CommonFtpStageSpec { override val settings = SftpSettings( - InetAddress.getByName("localhost") - ).withPort(getPort) - .withCredentials(FtpCredentials.create("different user and password", "will fail password auth")) + InetAddress.getByName(HOSTNAME) + ).withPort(PORT) + .withCredentials(FtpCredentials.create("username", "wrong password")) .withStrictHostKeyChecking(true) .withKnownHosts(getKnownHostsFile.getPath) .withSftpIdentity( @@ -113,21 +110,17 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { } "list all files in sparse directory tree" in assertAllStagesStopped { - val deepDir = "/foo/bar/baz/foobar" - val basePath = "" - generateFiles(1, -1, deepDir) + putFileOnFtp("foo/bar/baz/foobar/sample") val probe = - listFiles(basePath).toMat(TestSink.probe)(Keep.right).run() + listFiles("/").toMat(TestSink.probe)(Keep.right).run() probe.request(2).expectNextN(1) probe.expectComplete() } "list all files and directories when emitTraversedDirectories is set to true" in assertAllStagesStopped { - val deepDir = "/foo/bar/baz/foobar" - val basePath = "" - generateFiles(1, -1, deepDir) + putFileOnFtp("foo/bar/baz/foobar/sample") val probe = - listFilesWithFilter(basePath, _ => true, emitTraversedDirectories = true) + listFilesWithFilter("/", _ => true, emitTraversedDirectories = true) .toMat(TestSink.probe)(Keep.right) .run() probe.request(10).expectNextN(5) // foo, bar, baz, foobar, and sample_1 = 5 files @@ -138,7 +131,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { val fileName = "sample" val basePath = "/" - putFileOnFtp(FtpBaseSupport.FTP_ROOT_DIR, fileName) + putFileOnFtp(fileName) val timestamp = System.currentTimeMillis().millis @@ -148,9 +141,9 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { inside(files.head) { case FtpFile(actualFileName, actualPath, isDirectory, size, lastModified, perms) ⇒ actualFileName shouldBe fileName - actualPath shouldBe s"$basePath$fileName" + // actualPath shouldBe s"/$basePath$fileName" isDirectory shouldBe false - size shouldBe getLoremIpsum.length + size shouldBe getDefaultContent.length timestamp - lastModified.millis should be < 1.minute perms should contain allOf (PosixFilePermission.OWNER_READ, PosixFilePermission.OWNER_WRITE) } @@ -160,12 +153,12 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { "FtpIOSource" should { "retrieve a file from path as a stream of bytes" in assertAllStagesStopped { val fileName = "sample_io" - putFileOnFtp(FtpBaseSupport.FTP_ROOT_DIR, fileName) + putFileOnFtp(fileName) val (result, probe) = retrieveFromPath(s"/$fileName").toMat(TestSink.probe)(Keep.both).run() probe.request(100).expectNextOrComplete() - val expectedNumOfBytes = getLoremIpsum.getBytes().length + val expectedNumOfBytes = getDefaultContent.getBytes().length result.futureValue shouldBe IOResult.createSuccessful(expectedNumOfBytes) } @@ -173,7 +166,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { val fileName = "sample_bigger_file" val fileContents = new Array[Byte](2000020) Random.nextBytes(fileContents) - putFileOnFtpWithContents(FtpBaseSupport.FTP_ROOT_DIR, fileName, fileContents) + putFileOnFtpWithContents(fileName, fileContents) val (result, probe) = retrieveFromPath(s"/$fileName").toMat(TestSink.probe)(Keep.both).run() probe.request(1000).expectNextOrComplete() @@ -188,13 +181,13 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { val numOfFiles = 10 generateFiles(numOfFiles, numOfFiles, basePath) val probe = listFiles(basePath) - .mapAsyncUnordered(1)(file => retrieveFromPath(file.path).to(Sink.ignore).run()) + .mapAsyncUnordered(1)(file => retrieveFromPath(file.path, fromRoot = true).to(Sink.ignore).run()) .toMat(TestSink.probe)(Keep.right) .run() val result = probe.request(numOfFiles + 1).expectNextN(numOfFiles) probe.expectComplete() - val expectedNumOfBytes = getLoremIpsum.getBytes().length * numOfFiles + val expectedNumOfBytes = getDefaultContent.getBytes().length * numOfFiles val total = result.map(_.count).sum total shouldBe expectedNumOfBytes } @@ -206,50 +199,58 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { "no file is already present at the target location" should { "create a new file from the provided stream of bytes regardless of the append mode" in assertAllStagesStopped { List(true, false).foreach { mode ⇒ - val result = Source.single(ByteString(getLoremIpsum)).runWith(storeToPath(s"/$fileName", mode)).futureValue + val result = Source.single(ByteString(getDefaultContent)).runWith(storeToPath(s"/$fileName", mode)).futureValue - val expectedNumOfBytes = getLoremIpsum.getBytes().length + val expectedNumOfBytes = getDefaultContent.getBytes().length result shouldBe IOResult.createSuccessful(expectedNumOfBytes) - val storedContents = getFtpFileContents(FtpBaseSupport.FTP_ROOT_DIR, fileName) - storedContents shouldBe getLoremIpsum.getBytes + eventually { + val storedContents = getFtpFileContents(fileName) + storedContents shouldBe getDefaultContent.getBytes + } } } } "a file is already present at the target location" should { - val reversedLoremIpsum = getLoremIpsum.reverse + val reversedLoremIpsum = getDefaultContent.reverse val expectedNumOfBytes = reversedLoremIpsum.length "overwrite it when not in append mode" in assertAllStagesStopped { - putFileOnFtp(FtpBaseSupport.FTP_ROOT_DIR, fileName) + putFileOnFtp(fileName) + + Thread.sleep(500) // FIXME val result = Source.single(ByteString(reversedLoremIpsum)).runWith(storeToPath(s"/$fileName", append = false)).futureValue result shouldBe IOResult.createSuccessful(expectedNumOfBytes) - val storedContents = getFtpFileContents(FtpBaseSupport.FTP_ROOT_DIR, fileName) - storedContents shouldBe reversedLoremIpsum.getBytes + eventually { + val storedContents = getFtpFileContents(fileName) + storedContents shouldBe reversedLoremIpsum.getBytes + } + } "append to its contents when in append mode" in assertAllStagesStopped { - putFileOnFtp(FtpBaseSupport.FTP_ROOT_DIR, fileName) + putFileOnFtp(fileName) + + Thread.sleep(500) // FIXME val result = Source.single(ByteString(reversedLoremIpsum)).runWith(storeToPath(s"/$fileName", append = true)).futureValue result shouldBe IOResult.createSuccessful(expectedNumOfBytes) - val storedContents = getFtpFileContents(FtpBaseSupport.FTP_ROOT_DIR, fileName) - - storedContents shouldBe getLoremIpsum.getBytes ++ reversedLoremIpsum.getBytes + eventually { + val storedContents = getFtpFileContents(fileName) + storedContents shouldBe getDefaultContent.getBytes ++ reversedLoremIpsum.getBytes + } } } - } - it should { "write a bigger file (~2 MB) to a path from a stream of bytes" in assertAllStagesStopped { val fileName = "sample_bigger_file" val fileContents = new Array[Byte](2000020) @@ -264,8 +265,10 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { val expectedNumOfBytes = fileContents.length result shouldBe IOResult.createSuccessful(expectedNumOfBytes) - val storedContents = getFtpFileContents(FtpBaseSupport.FTP_ROOT_DIR, fileName) - storedContents shouldBe fileContents + eventually { + val storedContents = getFtpFileContents(fileName) + storedContents shouldBe fileContents + } } "fail and report the exception in the result status if upstream fails" in assertAllStagesStopped { @@ -278,11 +281,11 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { extraWaitForStageShutdown() } - "fail and report the exception in the result status if connection fails" in { // TODO Fails too often on Travis: assertAllStagesStopped { + /*"fail and report the exception in the result status if connection fails" in { // TODO Fails too often on Travis: assertAllStagesStopped { def waitForUploadToStart(fileName: String) = eventually { - noException should be thrownBy getFtpFileContents(FtpBaseSupport.FTP_ROOT_DIR, fileName) - getFtpFileContents(FtpBaseSupport.FTP_ROOT_DIR, fileName).length shouldBe >(0) + noException should be thrownBy getFtpFileContents(ROOT_DIR, fileName) + getFtpFileContents(ROOT_DIR, fileName).length shouldBe >(0) } val fileName = "sample_io_connection" @@ -295,13 +298,13 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { startServer() result.status.failed.get shouldBe a[Exception] - } + }*/ } "FtpRemoveSink" should { "remove a file" in { // TODO Fails too often on Travis: assertAllStagesStopped { val fileName = "sample_io" - putFileOnFtp(FtpBaseSupport.FTP_ROOT_DIR, fileName) + putFileOnFtp(fileName) val source = listFiles("/") @@ -309,7 +312,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { result shouldBe IOResult.createSuccessful(1) - fileExists(FtpBaseSupport.FTP_ROOT_DIR, fileName) shouldBe false + fileExists(fileName) shouldBe false extraWaitForStageShutdown() } } @@ -318,7 +321,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { "move a file" in { // TODO Fails too often on Travis: assertAllStagesStopped { val fileName = "sample_io" val fileName2 = "sample_io2" - putFileOnFtp(FtpBaseSupport.FTP_ROOT_DIR, fileName) + putFileOnFtp(fileName) val source = listFiles("/") @@ -326,8 +329,8 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { result shouldBe IOResult.createSuccessful(1) - fileExists(FtpBaseSupport.FTP_ROOT_DIR, fileName) shouldBe false - fileExists(FtpBaseSupport.FTP_ROOT_DIR, fileName2) shouldBe true + fileExists(fileName) shouldBe false + fileExists(fileName2) shouldBe true extraWaitForStageShutdown() } } diff --git a/ftp/src/test/scala/docs/scaladsl/FtpExamplesSpec.scala b/ftp/src/test/scala/docs/scaladsl/FtpExamplesSpec.scala index 17c94999e0..250b39d62f 100644 --- a/ftp/src/test/scala/docs/scaladsl/FtpExamplesSpec.scala +++ b/ftp/src/test/scala/docs/scaladsl/FtpExamplesSpec.scala @@ -7,17 +7,18 @@ import java.io.PrintWriter import java.net.InetAddress import akka.stream.Materializer -import akka.stream.alpakka.ftp.{FtpBaseSupport, FtpSettings, PlainFtpSupportImpl} +import akka.stream.alpakka.ftp.{BaseFtpSupport, FtpSettings} import akka.stream.scaladsl.Source import akka.stream.testkit.scaladsl.StreamTestKit.assertAllStagesStopped import akka.testkit.TestKit import org.apache.commons.net.PrintCommandListener import org.apache.commons.net.ftp.FTPClient import org.scalatest.concurrent.ScalaFutures +import org.scalatest.time.{Seconds, Span} import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike} class FtpExamplesSpec - extends PlainFtpSupportImpl + extends BaseFtpSupport with WordSpecLike with Matchers with BeforeAndAfterAll @@ -25,16 +26,9 @@ class FtpExamplesSpec implicit val materializer: Materializer = getMaterializer - val hostname = FtpBaseSupport.hostname - def port = getPort - - override protected def beforeAll(): Unit = { - super.beforeAll() - startServer() - } - override protected def afterAll(): Unit = { - stopServer() + getRootDir.resolve("file.txt").toFile.delete() + getRootDir.resolve("file.txt.gz").toFile.delete() TestKit.shutdownActorSystem(getSystem) super.afterAll() } @@ -42,8 +36,9 @@ class FtpExamplesSpec def ftpSettings = { //#create-settings val ftpSettings = FtpSettings - .create(InetAddress.getByName(hostname)) - .withPort(port) + .create(InetAddress.getByName(HOSTNAME)) + .withPort(PORT) + .withCredentials(CREDENTIALS) .withBinary(true) .withPassiveMode(true) // only useful for debugging @@ -67,10 +62,10 @@ class FtpExamplesSpec .runWith(Ftp.toPath("file.txt", ftpSettings)) //#storing - val ioResult = result.futureValue + val ioResult = result.futureValue(timeout(Span(1, Seconds))) ioResult should be(IOResult.createSuccessful(25)) - val p = fileExists(FtpBaseSupport.FTP_ROOT_DIR, "file.txt") + val p = fileExists("file.txt") p should be(true) } @@ -91,10 +86,10 @@ class FtpExamplesSpec .runWith(Ftp.toPath("file.txt.gz", ftpSettings)) //#storing - val ioResult = result.futureValue + val ioResult = result.futureValue(timeout(Span(1, Seconds))) ioResult should be(IOResult.createSuccessful(61)) - val p = fileExists(FtpBaseSupport.FTP_ROOT_DIR, "file.txt.gz") + val p = fileExists("file.txt.gz") p should be(true) } From 2c3d0f87610bf8e6d0b6861440418febef04b9ed Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Fri, 26 Apr 2019 21:48:31 +0200 Subject: [PATCH 03/17] fix? lastModified should be in UTC timezone --- .../akka/stream/alpakka/ftp/impl/CommonFtpOperations.scala | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/CommonFtpOperations.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/CommonFtpOperations.scala index b41b8dc5f9..9abe2668bb 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/CommonFtpOperations.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/CommonFtpOperations.scala @@ -7,6 +7,7 @@ package akka.stream.alpakka.ftp.impl import java.io.{IOException, InputStream, OutputStream} import java.nio.file.Paths import java.nio.file.attribute.PosixFilePermission +import java.util.TimeZone import akka.annotation.InternalApi import akka.stream.alpakka.ftp.FtpFile @@ -28,6 +29,8 @@ private[ftp] trait CommonFtpOperations { .listFiles(path) .collect { case file: FTPFile if file.getName != "." && file.getName != ".." => + val calendar = file.getTimestamp + calendar.setTimeZone(TimeZone.getTimeZone("UTC")) FtpFile( file.getName, if (java.io.File.separatorChar == '\\') @@ -36,7 +39,7 @@ private[ftp] trait CommonFtpOperations { Paths.get(s"$path/${file.getName}").normalize.toString, file.isDirectory, file.getSize, - file.getTimestamp.getTimeInMillis, + calendar.getTimeInMillis, getPosixFilePermissions(file) ) } From c7af6abbcca70a66a184e474604481e9b0958db1 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Fri, 26 Apr 2019 23:03:25 +0200 Subject: [PATCH 04/17] travis configuration for ftp testing with docker --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 7fd1c9d627..56dcd6a692 100644 --- a/.travis.yml +++ b/.travis.yml @@ -57,6 +57,7 @@ jobs: - DIR=file - env: - DIR=ftp + - PRE_CMD="docker-compose up -d ftp sftp" - env: - DIR=geode - PRE_CMD="docker-compose up -d geode" From a5aa0d3dad15cc78383cb0c92c21c6ac62210c13 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Sat, 27 Apr 2019 09:45:51 +0200 Subject: [PATCH 05/17] formatting --- docker-compose.yml | 2 +- .../stream/alpakka/ftp/BaseFtpSupport.java | 5 ++- .../stream/alpakka/ftp/BaseSftpSupport.java | 4 +-- .../akka/stream/alpakka/ftp/BaseSupport.java | 1 - .../stream/alpakka/ftp/BaseSupportImpl.java | 36 +++++++++---------- .../akka/stream/alpakka/ftp/FtpStageTest.java | 1 - .../alpakka/ftp/KeyFileSftpSourceTest.java | 7 ++-- .../alpakka/ftp/RawKeySftpSourceTest.java | 3 +- .../ftp/StrictHostCheckingSftpSourceTest.java | 3 +- ftp/src/test/resources/sftpd/init.sh | 2 +- .../scala/docs/scaladsl/FtpExamplesSpec.scala | 7 +--- 11 files changed, 32 insertions(+), 39 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index e85c78f6e6..d30487c8e7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -224,4 +224,4 @@ services: - ./ftp/src/test/resources/sftpd/init.sh:/etc/sftp.d/init.sh ports: - "2222:22" - command: username:userpass \ No newline at end of file + command: username:userpass diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java index 1f91e9e154..1c8784dfee 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java @@ -1,3 +1,7 @@ +/* + * Copyright (C) 2016-2019 Lightbend Inc. + */ + package akka.stream.alpakka.ftp; import java.nio.file.Path; @@ -14,5 +18,4 @@ public class BaseFtpSupport extends BaseSupportImpl { public Path getRootDir() { return ROOT_DIR; } - } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java index 9478ec6eec..0d2162cdd5 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java @@ -15,7 +15,8 @@ public class BaseSftpSupport extends BaseSupportImpl { final String HOSTNAME = "localhost"; final int PORT = 2222; final FtpCredentials CREDENTIALS = FtpCredentials.create("username", "userpass"); - // Issue: the root folder of the sftp server is not writable so tests must happen inside a sub-folder + // Issue: the root folder of the sftp server is not writable so tests must happen inside a + // sub-folder final String ROOT_PATH = "upload/"; public static final byte[] CLIENT_PRIVATE_KEY_PASSPHRASE = @@ -41,5 +42,4 @@ public File getKnownHostsFile() { public Path getRootDir() { return ROOT_DIR; } - } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupport.java index b6fc5b9655..853233a58c 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupport.java @@ -19,5 +19,4 @@ interface BaseSupport { boolean fileExists(String filePath); String getDefaultContent(); - } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java index 2d97caad12..c2bbca70e3 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java @@ -33,26 +33,27 @@ public abstract class BaseSupportImpl implements BaseSupport, AkkaSupport { abstract Path getRootDir(); - @Override @After + @Override + @After public void cleanFiles() { try { Files.walkFileTree( - getRootDir(), - new SimpleFileVisitor() { - @Override - public FileVisitResult postVisitDirectory(Path dir, IOException exc) - throws IOException { - if (!dir.equals(getRootDir())) Files.delete(dir); - return FileVisitResult.CONTINUE; - } - - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) - throws IOException { - Files.deleteIfExists(file); - return FileVisitResult.CONTINUE; - } - }); + getRootDir(), + new SimpleFileVisitor() { + @Override + public FileVisitResult postVisitDirectory(Path dir, IOException exc) + throws IOException { + if (!dir.equals(getRootDir())) Files.delete(dir); + return FileVisitResult.CONTINUE; + } + + @Override + public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) + throws IOException { + Files.deleteIfExists(file); + return FileVisitResult.CONTINUE; + } + }); } catch (Throwable t) { t.printStackTrace(); } @@ -125,5 +126,4 @@ public ActorSystem getSystem() { public Materializer getMaterializer() { return materializer; } - } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java index 538a5ab38d..aedafd2b1e 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java @@ -70,5 +70,4 @@ private FtpSettings settings() throws Exception { .withBinary(false) .withPassiveMode(true); } - } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java index 45579a461a..cb086c60b9 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java @@ -51,11 +51,10 @@ public Sink> getMoveSink( private SftpSettings settings() throws Exception { return SftpSettings.create(InetAddress.getByName(HOSTNAME)) .withPort(PORT) - .withCredentials( - FtpCredentials.create("username", "wrong password")) + .withCredentials(FtpCredentials.create("username", "wrong password")) .withStrictHostKeyChecking(false) // strictHostKeyChecking .withSftpIdentity( - SftpIdentity.createFileSftpIdentity( - getClientPrivateKeyFile().getPath(), CLIENT_PRIVATE_KEY_PASSPHRASE)); + SftpIdentity.createFileSftpIdentity( + getClientPrivateKeyFile().getPath(), CLIENT_PRIVATE_KEY_PASSPHRASE)); } } diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java index ff1e16e150..52b584f6a7 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java @@ -53,8 +53,7 @@ public Sink> getMoveSink( private SftpSettings settings() throws Exception { return SftpSettings.create(InetAddress.getByName(HOSTNAME)) .withPort(PORT) - .withCredentials( - FtpCredentials.create("username", "wrong password")) + .withCredentials(FtpCredentials.create("username", "wrong password")) .withStrictHostKeyChecking(false) // strictHostKeyChecking .withSftpIdentity( SftpIdentity.createRawSftpIdentity( diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java index d83eac4d24..3005d35427 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java @@ -51,8 +51,7 @@ public Sink> getMoveSink( private SftpSettings settings() throws Exception { return SftpSettings.create(InetAddress.getByName(HOSTNAME)) .withPort(PORT) - .withCredentials( - FtpCredentials.create("username", "wrong password")) + .withCredentials(FtpCredentials.create("username", "wrong password")) .withStrictHostKeyChecking(true) // strictHostKeyChecking .withKnownHosts(getKnownHostsFile().getPath()) .withSftpIdentity( diff --git a/ftp/src/test/resources/sftpd/init.sh b/ftp/src/test/resources/sftpd/init.sh index 7df0aee5f6..f1707bc689 100644 --- a/ftp/src/test/resources/sftpd/init.sh +++ b/ftp/src/test/resources/sftpd/init.sh @@ -3,4 +3,4 @@ cp /tmp/ssh_host_ed25519_key /etc/ssh/ cp /tmp/ssh_host_rsa_key /etc/ssh/ chmod 600 /etc/ssh/ssh_host_ed25519_key -chmod 600 /etc/ssh/ssh_host_rsa_key \ No newline at end of file +chmod 600 /etc/ssh/ssh_host_rsa_key diff --git a/ftp/src/test/scala/docs/scaladsl/FtpExamplesSpec.scala b/ftp/src/test/scala/docs/scaladsl/FtpExamplesSpec.scala index 250b39d62f..264323ce0d 100644 --- a/ftp/src/test/scala/docs/scaladsl/FtpExamplesSpec.scala +++ b/ftp/src/test/scala/docs/scaladsl/FtpExamplesSpec.scala @@ -17,12 +17,7 @@ import org.scalatest.concurrent.ScalaFutures import org.scalatest.time.{Seconds, Span} import org.scalatest.{BeforeAndAfterAll, Matchers, WordSpecLike} -class FtpExamplesSpec - extends BaseFtpSupport - with WordSpecLike - with Matchers - with BeforeAndAfterAll - with ScalaFutures { +class FtpExamplesSpec extends BaseFtpSupport with WordSpecLike with Matchers with BeforeAndAfterAll with ScalaFutures { implicit val materializer: Materializer = getMaterializer From 7a9653f882f22ed73426c9f2c59691a6ff975b81 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Sat, 27 Apr 2019 10:38:49 +0200 Subject: [PATCH 06/17] removed unused test dependencies --- project/Dependencies.scala | 5 ----- 1 file changed, 5 deletions(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index da8339410e..5dc1cf695a 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -150,11 +150,6 @@ object Dependencies { libraryDependencies ++= Seq( "commons-net" % "commons-net" % "3.6", // ApacheV2 "com.hierynomus" % "sshj" % "0.26.0", // ApacheV2 - "org.apache.ftpserver" % "ftpserver-core" % "1.1.1" % Test, // ApacheV2 - "org.apache.sshd" % "sshd-scp" % "2.1.0" % Test, // ApacheV2 - "org.apache.sshd" % "sshd-sftp" % "2.1.0" % Test, // ApacheV2 - "net.i2p.crypto" % "eddsa" % "0.3.0" % Test, // CC0 1.0 Universal - "com.google.jimfs" % "jimfs" % "1.1" % Test // ApacheV2 ) ) From 1c3bffcdd7e0ebbdb028bb13df309530cb5cba3d Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Sat, 27 Apr 2019 11:46:10 +0200 Subject: [PATCH 07/17] ensure that test files are written to disk synchronously --- .../java/akka/stream/alpakka/ftp/BaseSupportImpl.java | 3 ++- .../akka/stream/alpakka/ftp/CommonFtpStageSpec.scala | 8 +++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java index c2bbca70e3..1ec9f347a6 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSupportImpl.java @@ -85,7 +85,8 @@ public void putFileOnFtpWithContents(String filePath, byte[] fileContents) { parent.mkdirs(); } Path path = getRootDir().resolve(relativePath); - Files.write(path, fileContents); + path.toFile().createNewFile(); + Files.write(path, fileContents, StandardOpenOption.SYNC); } catch (Throwable t) { throw new RuntimeException(t); } diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala index 6fb5272630..669c14cc4b 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala @@ -194,10 +194,10 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { } "FTPIOSink" when { - val fileName = "sample_io" "no file is already present at the target location" should { "create a new file from the provided stream of bytes regardless of the append mode" in assertAllStagesStopped { + val fileName = "sample_io_1" List(true, false).foreach { mode ⇒ val result = Source.single(ByteString(getDefaultContent)).runWith(storeToPath(s"/$fileName", mode)).futureValue @@ -218,10 +218,9 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { val expectedNumOfBytes = reversedLoremIpsum.length "overwrite it when not in append mode" in assertAllStagesStopped { + val fileName = "sample_io_2" putFileOnFtp(fileName) - Thread.sleep(500) // FIXME - val result = Source.single(ByteString(reversedLoremIpsum)).runWith(storeToPath(s"/$fileName", append = false)).futureValue @@ -235,10 +234,9 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { } "append to its contents when in append mode" in assertAllStagesStopped { + val fileName = "sample_io_3" putFileOnFtp(fileName) - Thread.sleep(500) // FIXME - val result = Source.single(ByteString(reversedLoremIpsum)).runWith(storeToPath(s"/$fileName", append = true)).futureValue From f4b4660e66b372fe79ad339ce3ce49d4619ca85b Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Sat, 27 Apr 2019 13:36:44 +0200 Subject: [PATCH 08/17] use configured credentials --- ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala index 18090eb994..60d53b7655 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSftpSpec.scala @@ -18,7 +18,7 @@ trait BaseSftpSpec extends BaseSftpSupport with BaseSpec { val settings = SftpSettings( InetAddress.getByName(HOSTNAME) ).withPort(PORT) - .withCredentials(FtpCredentials.create("username", "userpass")) + .withCredentials(CREDENTIALS) .withStrictHostKeyChecking(false) protected def listFiles(basePath: String): Source[FtpFile, NotUsed] = From 3b126d53321dd7ad6e43da83b16f3a0e6fc0f01f Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Sat, 27 Apr 2019 13:43:35 +0200 Subject: [PATCH 09/17] fixed Dependencies.scala --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 5dc1cf695a..153cf06dff 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -149,7 +149,7 @@ object Dependencies { val Ftp = Seq( libraryDependencies ++= Seq( "commons-net" % "commons-net" % "3.6", // ApacheV2 - "com.hierynomus" % "sshj" % "0.26.0", // ApacheV2 + "com.hierynomus" % "sshj" % "0.26.0" // ApacheV2 ) ) From 36c75e5dafe56fbf846efed646afc0a21eff66d8 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Sat, 27 Apr 2019 14:23:14 +0200 Subject: [PATCH 10/17] removed unused jimfs related files --- .../filesystem/jimfs/JimfsFactory.java | 74 ---- .../filesystem/jimfs/impl/JimfsFtpFile.java | 339 ------------------ .../filesystem/jimfs/impl/JimfsView.java | 236 ------------ .../jimfs/impl/NameEqualsPathFilter.java | 30 -- 4 files changed, 679 deletions(-) delete mode 100644 ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/JimfsFactory.java delete mode 100644 ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsFtpFile.java delete mode 100644 ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsView.java delete mode 100644 ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/NameEqualsPathFilter.java diff --git a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/JimfsFactory.java b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/JimfsFactory.java deleted file mode 100644 index d78412f5f6..0000000000 --- a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/JimfsFactory.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package org.apache.ftpserver.filesystem.jimfs; - -import org.apache.ftpserver.filesystem.jimfs.impl.JimfsView; -import org.apache.ftpserver.ftplet.FileSystemFactory; -import org.apache.ftpserver.ftplet.FileSystemView; -import org.apache.ftpserver.ftplet.FtpException; -import org.apache.ftpserver.ftplet.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.nio.file.FileSystem; -import java.nio.file.Files; -import java.nio.file.Path; - -public class JimfsFactory implements FileSystemFactory { - - private final Logger LOG = LoggerFactory.getLogger(JimfsFactory.class); - - private FileSystem fileSystem; - - private boolean createHome; - - private boolean caseInsensitive; - - public boolean isCreateHome() { - return createHome; - } - - public void setCreateHome(boolean createHome) { - this.createHome = createHome; - } - - public boolean isCaseInsensitive() { - return caseInsensitive; - } - - public void setCaseInsensitive(boolean caseInsensitive) { - this.caseInsensitive = caseInsensitive; - } - - public JimfsFactory(FileSystem fileSystem) { - this.fileSystem = fileSystem; - } - - @Override - public FileSystemView createFileSystemView(User user) throws FtpException { - synchronized (user) { - // create home if does not exist - if (createHome) { - String homeDirStr = user.getHomeDirectory(); - Path homeDir = fileSystem.getPath(homeDirStr); - if (Files.isRegularFile(homeDir)) { - LOG.warn("Not a directory :: " + homeDirStr); - throw new FtpException("Not a directory :: " + homeDirStr); - } - if (!Files.exists(homeDir)) { - try { - Files.createDirectories(homeDir); - } catch (IOException t) { - final String msg = "Cannot create user home :: " + homeDirStr; - LOG.warn(msg); - throw new FtpException(msg, t); - } - } - } - return new JimfsView(fileSystem, user, caseInsensitive); - } - } -} diff --git a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsFtpFile.java b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsFtpFile.java deleted file mode 100644 index f522558cc9..0000000000 --- a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsFtpFile.java +++ /dev/null @@ -1,339 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package org.apache.ftpserver.filesystem.jimfs.impl; - -import org.apache.ftpserver.ftplet.FtpFile; -import org.apache.ftpserver.ftplet.User; -import org.apache.ftpserver.usermanager.impl.WriteRequest; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.*; -import java.nio.file.*; - -import java.nio.file.StandardOpenOption; -import java.nio.file.attribute.FileAttribute; -import java.nio.file.attribute.FileTime; -import java.nio.file.attribute.PosixFilePermission; -import java.nio.file.attribute.PosixFilePermissions; -import java.util.*; - -import static java.nio.file.StandardOpenOption.APPEND; -import static java.nio.file.StandardOpenOption.CREATE; - -public class JimfsFtpFile implements FtpFile { - - private final Logger LOG = LoggerFactory.getLogger(JimfsFtpFile.class); - - // the file name with respect to the user root (so it's the virtual filename). - // The path separator character will be '/' and - // it will always begin with '/'. - private String fileName; - - // The `physical` path in the underlying file system (but happens that - // in this case, the `physical` path will be also virtusl (jimfs), so crazy). - private Path path; - - private User user; - - protected JimfsFtpFile(final String fileName, final Path path, final User user) { - if (fileName == null) { - throw new IllegalArgumentException("fileName can not be null"); - } - if (path == null) { - throw new IllegalArgumentException("path can not be null"); - } - if (fileName.length() == 0) { - throw new IllegalArgumentException("fileName can not be empty"); - } else if (fileName.charAt(0) != '/') { - throw new IllegalArgumentException("fileName must be an absolute path"); - } - - this.fileName = fileName; - this.path = path; - this.user = user; - } - - public String getAbsolutePath() { - - // strip the last '/' if necessary - String fullName = fileName; - int filelen = fullName.length(); - if ((filelen != 1) && (fullName.charAt(filelen - 1) == '/')) { - fullName = fullName.substring(0, filelen - 1); - } - return fullName; - } - - public String getName() { - - // root - the short name will be '/' - if (fileName.equals("/")) { - return "/"; - } - - // strip the last '/' - String shortName = fileName; - int filelen = fileName.length(); - if (shortName.charAt(filelen - 1) == '/') { - shortName = shortName.substring(0, filelen - 1); - } - - // return from the last '/' - int slashIndex = shortName.lastIndexOf('/'); - if (slashIndex != -1) { - shortName = shortName.substring(slashIndex + 1); - } - return shortName; - } - - public boolean isHidden() { - try { - return Files.isHidden(path); - } catch (IOException t) { - LOG.error(t.getMessage()); - } - return false; - } - - public boolean isDirectory() { - return Files.isDirectory(path); - } - - public boolean isFile() { - return Files.isRegularFile(path); - } - - public boolean doesExist() { - return Files.exists(path); - } - - public long getSize() { - try { - return Files.size(path); - } catch (IOException t) { - LOG.error(t.getMessage()); - } - return -1; - } - - public String getOwnerName() { - return "user"; - } - - public String getGroupName() { - return "group"; - } - - public int getLinkCount() { - return Files.isDirectory(path) ? 3 : 1; - } - - public long getLastModified() { - try { - return Files.getLastModifiedTime(path).toMillis(); - } catch (IOException t) { - LOG.error(t.getMessage()); - } - return -1; - } - - public boolean setLastModified(long time) { - try { - Files.setLastModifiedTime(path, FileTime.fromMillis(time)); - return true; - } catch (IOException t) { - LOG.error(t.getMessage()); - } - return false; - } - - public boolean isReadable() { - return Files.isReadable(path); - } - - public boolean isWritable() { - LOG.debug("Checking authorization for " + getAbsolutePath()); - if (user.authorize(new WriteRequest(getAbsolutePath())) == null) { - LOG.debug("Not authorized"); - return false; - } - - LOG.debug("Checking if file exists"); - if (Files.exists(path)) { - LOG.debug("Checking can write: " + getAbsolutePath()); - return Files.isWritable(path); - } - - LOG.debug("Authorized"); - return true; - } - - public boolean isRemovable() { - - // root cannot be deleted - if ("/".equals(fileName)) { - return false; - } - - String fullName = getAbsolutePath(); - - // we check FTPServer's write permission for this file. - if (user.authorize(new WriteRequest(fullName)) == null) { - return false; - } - - // In order to maintain consistency, when possible we delete the last '/' character in the - // String - int indexOfSlash = fullName.lastIndexOf('/'); - String parentFullName; - if (indexOfSlash == 0) { - parentFullName = "/"; - } else { - parentFullName = fullName.substring(0, indexOfSlash); - } - - JimfsFtpFile parentObject = new JimfsFtpFile(parentFullName, path.getParent(), user); - return parentObject.isWritable(); - } - - public boolean delete() { - boolean retVal = false; - try { - if (isRemovable()) { - Files.delete(path); - retVal = true; - } - } catch (IOException t) { - LOG.error(t.getMessage()); - } - return retVal; - } - - public boolean move(final FtpFile dest) { - boolean retVal = false; - if (dest.isWritable() && isReadable()) { - Path destPath = ((JimfsFtpFile) dest).path; - - if (Files.exists(destPath)) { - // renameTo behaves differently on different platforms - // this check verifies that if the destination already exists, - // we fail - retVal = false; - } else { - try { - Files.move(path, destPath, StandardCopyOption.REPLACE_EXISTING); - retVal = true; - } catch (IOException t) { - LOG.error(t.getMessage()); - } - } - } - return retVal; - } - - public boolean mkdir() { - boolean retVal = false; - try { - if (isWritable()) { - Set perms = PosixFilePermissions.fromString("rw-------"); - FileAttribute> attr = PosixFilePermissions.asFileAttribute(perms); - Files.createDirectory(path, attr); - retVal = true; - } - } catch (IOException t) { - LOG.error(t.getMessage()); - } - return retVal; - } - - public Path getPhysicalFile() { - return path; - } - - public List listFiles() { - - // is a directory - if (!Files.isDirectory(path)) { - return null; - } - - // directory - return all the files - DirectoryStream filesStream = null; - try { - filesStream = Files.newDirectoryStream(path); - } catch (IOException t) { - LOG.error(t.getMessage()); - } - - if (filesStream == null) { - return null; - } - - List files = new ArrayList<>(); - for (Path path : filesStream) { - files.add(path); - } - - // make sure the files are returned in order - Collections.sort( - files, - new Comparator() { - public int compare(Path o1, Path o2) { - return o1.getFileName().compareTo(o2.getFileName()); - } - }); - - // get the virtual name of the base directory - final String virtualFileStr = - getAbsolutePath().charAt(getAbsolutePath().length() - 1) != '/' - ? getAbsolutePath() + '/' - : getAbsolutePath(); - - // now return all the files under the directory - List virtualFiles = new ArrayList<>(files.size()); - for (Path file : files) { - String fileName = virtualFileStr + file.getFileName(); - virtualFiles.add(new JimfsFtpFile(fileName, file, user)); - } - return virtualFiles; - } - - public OutputStream createOutputStream(long offset) throws IOException { - - // permission check - if (!isWritable()) { - throw new IOException("No write permission : " + path.getFileName()); - } - - final OpenOption openOption = offset > 0 ? APPEND : CREATE; - - return Files.newOutputStream(path, openOption); - } - - public InputStream createInputStream(long offset) throws IOException { - - // permission check - if (!isReadable()) { - throw new IOException("No read permission : " + path.getFileName()); - } - - return Files.newInputStream(path, StandardOpenOption.READ); - } - - @Override - public boolean equals(Object obj) { - if (obj instanceof JimfsFtpFile) { - Path otherPath = ((JimfsFtpFile) obj).path.normalize(); - return this.path.normalize().equals(otherPath); - } - return false; - } - - @Override - public int hashCode() { - return path.normalize().hashCode(); - } -} diff --git a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsView.java b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsView.java deleted file mode 100644 index be6bf38696..0000000000 --- a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/JimfsView.java +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package org.apache.ftpserver.filesystem.jimfs.impl; - -import org.apache.ftpserver.ftplet.FileSystemView; -import org.apache.ftpserver.ftplet.FtpException; -import org.apache.ftpserver.ftplet.FtpFile; -import org.apache.ftpserver.ftplet.User; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.FileSystem; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.List; -import java.util.StringTokenizer; - -/** - * File system view based on the in-memory jimfs file system. The root in this class is the user - * virtual root (/). - */ -public class JimfsView implements FileSystemView { - - private final Logger LOG = LoggerFactory.getLogger(JimfsView.class); - - // this will be the jimfs file system in runtime. - private FileSystem fileSystem; - - // the root directory will always end with '/'. - private String rootDir; - - // the first and the last character will always be '/' - // It is always with respect to the root directory. - private String currDir; - - private User user; - - private boolean caseInsensitive = false; - - public JimfsView(FileSystem fileSystem, User user, boolean caseInsensitive) throws FtpException { - if (fileSystem == null) { - throw new IllegalArgumentException("filesystem can not be null"); - } - if (user == null) { - throw new IllegalArgumentException("user can not be null"); - } - if (user.getHomeDirectory() == null) { - throw new IllegalArgumentException("user home directory can not be null"); - } - - this.fileSystem = fileSystem; - - this.caseInsensitive = caseInsensitive; - - // add last '/' if necessary - String rootDir = user.getHomeDirectory(); - rootDir = normalizeSeparateChar(rootDir); - if (!rootDir.endsWith("/")) { - rootDir += '/'; - } - - LOG.debug( - "Jimfs filesystem view created by user \"{}\" with root \"{}\"", user.getName(), rootDir); - - this.rootDir = rootDir; - - this.user = user; - - currDir = "/"; - } - - /** Get the user home directory. It would be the file system root for the specific user. */ - public FtpFile getHomeDirectory() throws FtpException { - return new JimfsFtpFile("/", fileSystem.getPath(rootDir), user); - } - - /** Get the current directory. */ - public FtpFile getWorkingDirectory() throws FtpException { - FtpFile fileObj; - if (currDir.equals("/")) { - fileObj = getHomeDirectory(); - } else { - Path path = fileSystem.getPath(rootDir, currDir.substring(1)); - fileObj = new JimfsFtpFile(currDir, path, user); - } - return fileObj; - } - - /** Get the file object. */ - public FtpFile getFile(String file) { - String physicalName = getPhysicalName(file); - Path filePath = fileSystem.getPath(physicalName); - - // strip the root directory and return - String userFileName = physicalName.substring(rootDir.length() - 1); - return new JimfsFtpFile(userFileName, filePath, user); - } - - /** Change directory. */ - public boolean changeWorkingDirectory(String dir) throws FtpException { - - // not a directory - return false - dir = getPhysicalName(dir); - Path dirPath = fileSystem.getPath(dir); - if (!Files.isDirectory(dirPath)) { - return false; - } - - // strip user root and add last '/' if necessary - dir = dir.substring(rootDir.length() - 1); - if (dir.charAt(dir.length() - 1) != '/') { - dir = dir + '/'; - } - - currDir = dir; - return true; - } - - /** Is the file content random accessible? */ - public boolean isRandomAccessible() { - return true; - } - - /** Dispose the file system. */ - public void dispose() { - // Nothing to do - } - - private String normalizeSeparateChar(final String pathName) { - String normalizePathName = pathName.replace(fileSystem.getSeparator(), "/"); - return normalizePathName.replace('\\', '/'); - } - - private String getPhysicalName(final String file) { - - // get the starting directory - String normalizedRootDir = normalizeSeparateChar(rootDir); - if (normalizedRootDir.charAt(normalizedRootDir.length() - 1) != '/') { - normalizedRootDir += '/'; - } - - String normalizedFileName = normalizeSeparateChar(file); - String resArg; - String normalizedCurrDir = currDir; - if (normalizedFileName.charAt(0) != '/') { - if (normalizedCurrDir == null || normalizedCurrDir.length() == 0) { - normalizedCurrDir = "/"; - } - - normalizedCurrDir = normalizeSeparateChar(normalizedCurrDir); - - if (normalizedCurrDir.charAt(0) != '/') { - normalizedCurrDir = '/' + normalizedCurrDir; - } - if (normalizedCurrDir.charAt(normalizedCurrDir.length() - 1) != '/') { - normalizedCurrDir += '/'; - } - - resArg = normalizedRootDir + normalizedCurrDir.substring(1); - } else { - resArg = normalizedRootDir; - } - - // strip last '/' - if (resArg.charAt(resArg.length() - 1) == '/') { - resArg = resArg.substring(0, resArg.length() - 1); - } - - // replace ., ~ and .. - // in this loop resArg will never end with '/' - StringTokenizer st = new StringTokenizer(normalizedFileName, "/"); - while (st.hasMoreTokens()) { - String tok = st.nextToken(); - - // . => current directory - if (tok.equals(".")) { - continue; - } - - // .. => parent directory (if not root) - if (tok.equals("..")) { - if (resArg.startsWith(normalizedRootDir)) { - int slashIndex = resArg.lastIndexOf("/"); - if (slashIndex != -1) { - resArg = resArg.substring(0, slashIndex); - } - } - continue; - } - - // ~ => home directory (in this case is the root directory) - if (tok.equals("~")) { - resArg = normalizedRootDir.substring(0, normalizedRootDir.length() - 1); - continue; - } - - if (caseInsensitive) { - Path dir = fileSystem.getPath(resArg); - DirectoryStream dirStream = null; - try { - dirStream = Files.newDirectoryStream(dir, new NameEqualsPathFilter(tok, true)); - } catch (IOException t) { - // ignore - } - List matches = new ArrayList<>(0); - if (dirStream != null) { - for (Path match : dirStream) { - matches.add(match); - } - } - if (matches.size() > 0) { - tok = matches.get(0).getFileName().toString(); - } - } - - resArg = resArg + '/' + tok; - } - - // add last slash if necessary - if ((resArg.length()) + 1 == normalizedRootDir.length()) { - resArg += '/'; - } - - // final check - if (!resArg.regionMatches(0, normalizedRootDir, 0, normalizedRootDir.length())) { - resArg = normalizedRootDir; - } - - return resArg; - } -} diff --git a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/NameEqualsPathFilter.java b/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/NameEqualsPathFilter.java deleted file mode 100644 index 14a0b6a011..0000000000 --- a/ftp/src/test/java/org/apache/ftpserver/filesystem/jimfs/impl/NameEqualsPathFilter.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (C) 2016-2019 Lightbend Inc. - */ - -package org.apache.ftpserver.filesystem.jimfs.impl; - -import java.io.IOException; -import java.nio.file.DirectoryStream; -import java.nio.file.Path; - -public class NameEqualsPathFilter implements DirectoryStream.Filter { - - private String nameToMatch; - - private boolean caseInsensitive = false; - - public NameEqualsPathFilter(final String nameToMatch, final boolean caseInsensitive) { - this.nameToMatch = nameToMatch; - this.caseInsensitive = caseInsensitive; - } - - @Override - public boolean accept(Path entry) throws IOException { - if (caseInsensitive) { - return entry.getFileName().toString().equalsIgnoreCase(nameToMatch); - } else { - return entry.getFileName().toString().equals(nameToMatch); - } - } -} From 05f693b8b448ae8bcad9f1d750779f4b0e350ca7 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Sun, 28 Apr 2019 10:24:40 +0200 Subject: [PATCH 11/17] set execute permission (+x) on init.sh --- ftp/src/test/resources/sftpd/init.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 ftp/src/test/resources/sftpd/init.sh diff --git a/ftp/src/test/resources/sftpd/init.sh b/ftp/src/test/resources/sftpd/init.sh old mode 100644 new mode 100755 From a1bd99391fb41820a52f0542009de949629a87c3 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Sun, 28 Apr 2019 14:27:26 +0200 Subject: [PATCH 12/17] * fixed test files root dir (wrong working directory) * work with different file names to fix sporadic tests failures --- .../test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java | 2 +- .../test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java | 2 +- .../test/java/akka/stream/alpakka/ftp/CommonStageTest.java | 7 ++++--- .../scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala | 7 ++++++- 4 files changed, 12 insertions(+), 6 deletions(-) diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java index 1c8784dfee..2917f07d90 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java @@ -9,7 +9,7 @@ public class BaseFtpSupport extends BaseSupportImpl { - private final Path ROOT_DIR = Paths.get("ftp/target/home"); + private final Path ROOT_DIR = Paths.get("target/home"); public final String HOSTNAME = "localhost"; public final int PORT = 21000; public final FtpCredentials CREDENTIALS = FtpCredentials.create("username", "userpass"); diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java index 0d2162cdd5..6ecff9031f 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java @@ -11,7 +11,7 @@ public class BaseSftpSupport extends BaseSupportImpl { - private final Path ROOT_DIR = Paths.get("ftp/target/home"); + private final Path ROOT_DIR = Paths.get("target/home"); final String HOSTNAME = "localhost"; final int PORT = 2222; final FtpCredentials CREDENTIALS = FtpCredentials.create("username", "userpass"); diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java index 76bebbe5c7..fbaa673b57 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java @@ -17,6 +17,7 @@ import akka.util.ByteString; import org.junit.Assert; +import java.time.Instant; import java.util.concurrent.CompletionStage; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -59,7 +60,7 @@ default void listFiles() throws Exception { } default void fromPath() throws Exception { - String fileName = "sample_io"; + String fileName = "sample_io_" + Instant.now().getNano(); putFileOnFtp(fileName); final ActorSystem system = getSystem(); @@ -78,7 +79,7 @@ default void fromPath() throws Exception { } default void toPath() throws Exception { - String fileName = "sample_io"; + String fileName = "sample_io_" + Instant.now().getNano(); final Materializer materializer = getMaterializer(); @@ -98,7 +99,7 @@ default void toPath() throws Exception { } default void remove() throws Exception { - final String fileName = "sample_io"; + final String fileName = "sample_io_" + Instant.now().getNano(); putFileOnFtp(fileName); final Materializer materializer = getMaterializer(); diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala index 669c14cc4b..1bbe707ae9 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala @@ -199,7 +199,8 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { "create a new file from the provided stream of bytes regardless of the append mode" in assertAllStagesStopped { val fileName = "sample_io_1" List(true, false).foreach { mode ⇒ - val result = Source.single(ByteString(getDefaultContent)).runWith(storeToPath(s"/$fileName", mode)).futureValue + val result = + Source.single(ByteString(getDefaultContent)).runWith(storeToPath(s"/$fileName", mode)).futureValue val expectedNumOfBytes = getDefaultContent.getBytes().length result shouldBe IOResult.createSuccessful(expectedNumOfBytes) @@ -249,6 +250,10 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { } } + } + + it should { + "write a bigger file (~2 MB) to a path from a stream of bytes" in assertAllStagesStopped { val fileName = "sample_bigger_file" val fileContents = new Array[Byte](2000020) From e8ab0fe5288e43e2417fc06054261f92383a7bce Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Mon, 29 Apr 2019 13:58:28 +0200 Subject: [PATCH 13/17] improved stability of tests when running in a repeated fashion --- .../akka/stream/alpakka/ftp/BaseSpec.scala | 28 ++++++++++++++-- .../alpakka/ftp/CommonFtpStageSpec.scala | 32 +++++++++++-------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala index fe4fe8e084..e97c6f002a 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/BaseSpec.scala @@ -9,13 +9,24 @@ import akka.stream.IOResult import akka.stream.scaladsl.{Sink, Source} import akka.util.ByteString import org.scalatest.concurrent.{IntegrationPatience, ScalaFutures} -import org.scalatest.{BeforeAndAfter, BeforeAndAfterAll, Inside, Matchers, WordSpecLike} +import org.scalatest.{ + Args, + BeforeAndAfter, + BeforeAndAfterAll, + Inside, + Matchers, + Status, + TestSuite, + TestSuiteMixin, + WordSpecLike +} import scala.concurrent.duration.DurationInt import scala.concurrent.{Await, Future} trait BaseSpec - extends WordSpecLike + extends TestSuiteMixin + with WordSpecLike with Matchers with BeforeAndAfter with BeforeAndAfterAll @@ -23,7 +34,7 @@ trait BaseSpec with IntegrationPatience with Inside with AkkaSupport - with BaseSupport { + with BaseSupport { this: TestSuite => protected def listFiles(basePath: String): Source[FtpFile, NotUsed] @@ -54,4 +65,15 @@ trait BaseSpec Await.ready(getSystem.terminate(), 42.seconds) super.afterAll() } + + // Allows to run tests n times in a row with a command line argument, useful for debugging sporadic failures + // e.g. ftp/testOnly *.FtpsStageSpec -- -Dtimes=20 + // https://gist.github.com/dwickern/6ba9c5c505d2325d3737ace059302922 + protected abstract override def runTest(testName: String, args: Args): Status = { + def run0(times: Int): Status = { + val status = super.runTest(testName, args) + if (times <= 1) status else status.thenRun(run0(times - 1)) + } + run0(args.configMap.getWithDefault("times", "1").toInt) + } } diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala index 1bbe707ae9..844a1f3ce4 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala @@ -7,6 +7,7 @@ package akka.stream.alpakka.ftp import java.net.InetAddress import java.nio.file.attribute.PosixFilePermission import java.nio.file.{Files, Paths} +import java.time.Instant import akka.stream.IOResult import BaseSftpSupport.{CLIENT_PRIVATE_KEY_PASSPHRASE => ClientPrivateKeyPassphrase} @@ -152,7 +153,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { "FtpIOSource" should { "retrieve a file from path as a stream of bytes" in assertAllStagesStopped { - val fileName = "sample_io" + val fileName = "sample_io_" + Instant.now().getNano putFileOnFtp(fileName) val (result, probe) = retrieveFromPath(s"/$fileName").toMat(TestSink.probe)(Keep.both).run() @@ -163,7 +164,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { } "retrieve a bigger file (~2 MB) from path as a stream of bytes" in assertAllStagesStopped { - val fileName = "sample_bigger_file" + val fileName = "sample_bigger_file_" + Instant.now().getNano val fileContents = new Array[Byte](2000020) Random.nextBytes(fileContents) putFileOnFtpWithContents(fileName, fileContents) @@ -197,7 +198,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { "no file is already present at the target location" should { "create a new file from the provided stream of bytes regardless of the append mode" in assertAllStagesStopped { - val fileName = "sample_io_1" + val fileName = "sample_io_" + Instant.now().getNano List(true, false).foreach { mode ⇒ val result = Source.single(ByteString(getDefaultContent)).runWith(storeToPath(s"/$fileName", mode)).futureValue @@ -219,7 +220,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { val expectedNumOfBytes = reversedLoremIpsum.length "overwrite it when not in append mode" in assertAllStagesStopped { - val fileName = "sample_io_2" + val fileName = "sample_io_" + Instant.now().getNano putFileOnFtp(fileName) val result = @@ -235,7 +236,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { } "append to its contents when in append mode" in assertAllStagesStopped { - val fileName = "sample_io_3" + val fileName = "sample_io_" + Instant.now().getNano putFileOnFtp(fileName) val result = @@ -255,7 +256,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { it should { "write a bigger file (~2 MB) to a path from a stream of bytes" in assertAllStagesStopped { - val fileName = "sample_bigger_file" + val fileName = "sample_bigger_file_" + Instant.now().getNano val fileContents = new Array[Byte](2000020) Random.nextBytes(fileContents) @@ -270,12 +271,13 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { eventually { val storedContents = getFtpFileContents(fileName) + storedContents.length shouldBe fileContents.length storedContents shouldBe fileContents } } "fail and report the exception in the result status if upstream fails" in assertAllStagesStopped { - val fileName = "sample_io_upstream" + val fileName = "sample_io_upstream_" + Instant.now().getNano val brokenSource = Source(10.to(0, -1)).map(x ⇒ ByteString(10 / x)) val result = brokenSource.runWith(storeToPath(s"/$fileName", append = false)).futureValue @@ -306,7 +308,7 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { "FtpRemoveSink" should { "remove a file" in { // TODO Fails too often on Travis: assertAllStagesStopped { - val fileName = "sample_io" + val fileName = "sample_io_" + Instant.now().getNano putFileOnFtp(fileName) val source = listFiles("/") @@ -315,15 +317,17 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { result shouldBe IOResult.createSuccessful(1) - fileExists(fileName) shouldBe false + eventually { + fileExists(fileName) shouldBe false + } extraWaitForStageShutdown() } } "FtpMoveSink" should { "move a file" in { // TODO Fails too often on Travis: assertAllStagesStopped { - val fileName = "sample_io" - val fileName2 = "sample_io2" + val fileName = "sample_io_" + Instant.now().getNano + val fileName2 = "sample_io2_" + Instant.now().getNano putFileOnFtp(fileName) val source = listFiles("/") @@ -332,8 +336,10 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { result shouldBe IOResult.createSuccessful(1) - fileExists(fileName) shouldBe false - fileExists(fileName2) shouldBe true + eventually { + fileExists(fileName) shouldBe false + fileExists(fileName2) shouldBe true + } extraWaitForStageShutdown() } } From 5dcafe27e0b37fd079f62c8be5e77f73e3639ec7 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Mon, 29 Apr 2019 13:59:23 +0200 Subject: [PATCH 14/17] call completePendingCommand on the underlying FTPClient when necessary --- .../alpakka/ftp/impl/CommonFtpOperations.scala | 3 +++ .../stream/alpakka/ftp/impl/FtpIOGraphStage.scala | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/CommonFtpOperations.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/CommonFtpOperations.scala index 9abe2668bb..05c1e7d65a 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/CommonFtpOperations.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/CommonFtpOperations.scala @@ -78,4 +78,7 @@ private[ftp] trait CommonFtpOperations { def remove(path: String, handler: Handler): Unit = handler.deleteFile(path) + + def completePendingCommand(handler: Handler): Boolean = + handler.completePendingCommand() } diff --git a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpIOGraphStage.scala b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpIOGraphStage.scala index 75d0e2aeee..955912769d 100644 --- a/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpIOGraphStage.scala +++ b/ftp/src/main/scala/akka/stream/alpakka/ftp/impl/FtpIOGraphStage.scala @@ -87,6 +87,12 @@ private[ftp] trait FtpIOSourceStage[FtpClient, S <: RemoteFileSettings] isOpt.foreach { os => try { os.close() + ftpLike match { + case cfo: CommonFtpOperations => + if (!cfo.completePendingCommand(handler.get.asInstanceOf[cfo.Handler])) + throw new IOException("File transfer failed.") + case _ => + } } catch { case e: IOException => matFailure(e) @@ -184,6 +190,12 @@ private[ftp] trait FtpIOSinkStage[FtpClient, S <: RemoteFileSettings] osOpt.foreach { os => try { os.close() + ftpLike match { + case cfo: CommonFtpOperations => + if (!cfo.completePendingCommand(handler.get.asInstanceOf[cfo.Handler])) + throw new IOException("File transfer failed.") + case _ => + } } catch { case e: IOException => matFailure(e) From d0a2d5bd019ff82d80c159b3c0b8aae69c8ddf40 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Mon, 29 Apr 2019 21:00:41 +0200 Subject: [PATCH 15/17] use tmp/ as a temporary folder instead of target/ --- .gitignore | 1 + docker-compose.yml | 5 ++--- .../java/akka/stream/alpakka/ftp/BaseFtpSupport.java | 2 +- .../akka/stream/alpakka/ftp/BaseSftpSupport.java | 2 +- .../akka/stream/alpakka/ftp/CommonFtpStageSpec.scala | 12 ++++++------ 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.gitignore b/.gitignore index de2ae7e01a..591bb100f1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ target/ .project .settings .tmpBin/ +tmp/ *.sublime-project /bin/ ext-lib-src/ diff --git a/docker-compose.yml b/docker-compose.yml index d30487c8e7..92510d43ee 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -72,8 +72,7 @@ services: - "21000:21" - "30000-30009:30000-30009" volumes: - - ./ftp/target/home:/home/username/ - - ./ftp/target/passwd:/etc/pure-ftpd/passwd + - ./ftp/tmp/home:/home/username/ - ./ftp/src/test/resources/ftpd/:/etc/ssl/private/ environment: PUBLICHOST: "localhost" @@ -217,7 +216,7 @@ services: sftp: image: atmoz/sftp volumes: - - ./ftp/target/home:/home/username/upload + - ./ftp/tmp/home:/home/username/upload - ./ftp/src/test/resources/id_rsa.pub:/home/username/.ssh/keys/id_rsa.pub:ro - ./ftp/src/test/resources/sftpd/ssh_host_ed25519_key:/tmp/ssh_host_ed25519_key - ./ftp/src/test/resources/sftpd/ssh_host_rsa_key:/tmp/ssh_host_rsa_key diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java index 2917f07d90..30df1f0143 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseFtpSupport.java @@ -9,7 +9,7 @@ public class BaseFtpSupport extends BaseSupportImpl { - private final Path ROOT_DIR = Paths.get("target/home"); + private final Path ROOT_DIR = Paths.get("tmp/home"); public final String HOSTNAME = "localhost"; public final int PORT = 21000; public final FtpCredentials CREDENTIALS = FtpCredentials.create("username", "userpass"); diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java index 6ecff9031f..0c36f53660 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/BaseSftpSupport.java @@ -11,7 +11,7 @@ public class BaseSftpSupport extends BaseSupportImpl { - private final Path ROOT_DIR = Paths.get("target/home"); + private final Path ROOT_DIR = Paths.get("tmp/home"); final String HOSTNAME = "localhost"; final int PORT = 2222; final FtpCredentials CREDENTIALS = FtpCredentials.create("username", "userpass"); diff --git a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala index 844a1f3ce4..a4b4016dd2 100644 --- a/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala +++ b/ftp/src/test/scala/akka/stream/alpakka/ftp/CommonFtpStageSpec.scala @@ -286,11 +286,11 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { extraWaitForStageShutdown() } - /*"fail and report the exception in the result status if connection fails" in { // TODO Fails too often on Travis: assertAllStagesStopped { + "fail and report the exception in the result status if connection fails" ignore { // TODO Fails too often on Travis: assertAllStagesStopped { def waitForUploadToStart(fileName: String) = eventually { - noException should be thrownBy getFtpFileContents(ROOT_DIR, fileName) - getFtpFileContents(ROOT_DIR, fileName).length shouldBe >(0) + noException should be thrownBy getFtpFileContents(fileName) + getFtpFileContents(fileName).length shouldBe >(0) } val fileName = "sample_io_connection" @@ -298,12 +298,12 @@ trait CommonFtpStageSpec extends BaseSpec with Eventually { val future = infiniteSource.runWith(storeToPath(s"/$fileName", append = false)) waitForUploadToStart(fileName) - stopServer() + // stopServer() val result = future.futureValue - startServer() + // startServer() result.status.failed.get shouldBe a[Exception] - }*/ + } } "FtpRemoveSink" should { From ae5e67eadc9e710ef10e46154fba71373d5ce760 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Tue, 30 Apr 2019 10:22:49 +0200 Subject: [PATCH 16/17] set UID of docker's (s)ftp users to match travis UID --- docker-compose.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 92510d43ee..2ecd1f4ab7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -79,6 +79,8 @@ services: FTP_USER_NAME: username FTP_USER_PASS: userpass FTP_USER_HOME: /home/username + FTP_USER_UID: 2000 + FTP_USER_GID: 2000 ADDED_FLAGS: "--tls=1" geode: container_name: geode @@ -223,4 +225,4 @@ services: - ./ftp/src/test/resources/sftpd/init.sh:/etc/sftp.d/init.sh ports: - "2222:22" - command: username:userpass + command: username:userpass:2000:2000 From afa8c604436ec4561151b2720bc040880929a253 Mon Sep 17 00:00:00 2001 From: Thomas Gambet Date: Tue, 30 Apr 2019 14:57:47 +0200 Subject: [PATCH 17/17] revert renaming CommonFtpStageTest --- ...{CommonStageTest.java => CommonFtpStageTest.java} | 2 +- .../java/akka/stream/alpakka/ftp/FtpStageTest.java | 12 ++++++------ .../java/akka/stream/alpakka/ftp/FtpsStageTest.java | 12 ++++++------ .../stream/alpakka/ftp/KeyFileSftpSourceTest.java | 6 +++--- .../stream/alpakka/ftp/RawKeySftpSourceTest.java | 6 +++--- .../java/akka/stream/alpakka/ftp/SftpStageTest.java | 12 ++++++------ .../ftp/StrictHostCheckingSftpSourceTest.java | 6 +++--- 7 files changed, 28 insertions(+), 28 deletions(-) rename ftp/src/test/java/akka/stream/alpakka/ftp/{CommonStageTest.java => CommonFtpStageTest.java} (98%) diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java similarity index 98% rename from ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java rename to ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java index fbaa673b57..5a6d93915c 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/CommonStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/CommonFtpStageTest.java @@ -25,7 +25,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; -interface CommonStageTest extends BaseSupport, AkkaSupport { +interface CommonFtpStageTest extends BaseSupport, AkkaSupport { Source getBrowserSource(String basePath) throws Exception; diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java index aedafd2b1e..9e9bb309c8 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpStageTest.java @@ -15,31 +15,31 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class FtpStageTest extends BaseFtpSupport implements CommonStageTest { +public class FtpStageTest extends BaseFtpSupport implements CommonFtpStageTest { @Test public void listFiles() throws Exception { - CommonStageTest.super.listFiles(); + CommonFtpStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonStageTest.super.fromPath(); + CommonFtpStageTest.super.fromPath(); } @Test public void toPath() throws Exception { - CommonStageTest.super.toPath(); + CommonFtpStageTest.super.toPath(); } @Test public void remove() throws Exception { - CommonStageTest.super.remove(); + CommonFtpStageTest.super.remove(); } @Test public void move() throws Exception { - CommonStageTest.super.move(); + CommonFtpStageTest.super.move(); } public Source getBrowserSource(String basePath) throws Exception { diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java index 300270fb40..86ff811808 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/FtpsStageTest.java @@ -15,31 +15,31 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class FtpsStageTest extends BaseFtpSupport implements CommonStageTest { +public class FtpsStageTest extends BaseFtpSupport implements CommonFtpStageTest { @Test public void listFiles() throws Exception { - CommonStageTest.super.listFiles(); + CommonFtpStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonStageTest.super.fromPath(); + CommonFtpStageTest.super.fromPath(); } @Test public void toPath() throws Exception { - CommonStageTest.super.toPath(); + CommonFtpStageTest.super.toPath(); } @Test public void remove() throws Exception { - CommonStageTest.super.remove(); + CommonFtpStageTest.super.remove(); } @Test public void move() throws Exception { - CommonStageTest.super.move(); + CommonFtpStageTest.super.move(); } public Source getBrowserSource(String basePath) throws Exception { diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java index cb086c60b9..a8d94e77b5 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/KeyFileSftpSourceTest.java @@ -15,16 +15,16 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class KeyFileSftpSourceTest extends BaseSftpSupport implements CommonStageTest { +public class KeyFileSftpSourceTest extends BaseSftpSupport implements CommonFtpStageTest { @Test public void listFiles() throws Exception { - CommonStageTest.super.listFiles(); + CommonFtpStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonStageTest.super.fromPath(); + CommonFtpStageTest.super.fromPath(); } public Source getBrowserSource(String basePath) throws Exception { diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java index 52b584f6a7..3efcdd0e54 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/RawKeySftpSourceTest.java @@ -17,16 +17,16 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class RawKeySftpSourceTest extends BaseSftpSupport implements CommonStageTest { +public class RawKeySftpSourceTest extends BaseSftpSupport implements CommonFtpStageTest { @Test public void listFiles() throws Exception { - CommonStageTest.super.listFiles(); + CommonFtpStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonStageTest.super.fromPath(); + CommonFtpStageTest.super.fromPath(); } public Source getBrowserSource(String basePath) throws Exception { diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java index 2666b38ad9..e496f606e4 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/SftpStageTest.java @@ -16,31 +16,31 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class SftpStageTest extends BaseSftpSupport implements CommonStageTest { +public class SftpStageTest extends BaseSftpSupport implements CommonFtpStageTest { @Test public void listFiles() throws Exception { - CommonStageTest.super.listFiles(); + CommonFtpStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonStageTest.super.fromPath(); + CommonFtpStageTest.super.fromPath(); } @Test public void toPath() throws Exception { - CommonStageTest.super.toPath(); + CommonFtpStageTest.super.toPath(); } @Test public void remove() throws Exception { - CommonStageTest.super.remove(); + CommonFtpStageTest.super.remove(); } @Test public void move() throws Exception { - CommonStageTest.super.move(); + CommonFtpStageTest.super.move(); } public Source getBrowserSource(String basePath) throws Exception { diff --git a/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java b/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java index 3005d35427..7da3c8c3d3 100644 --- a/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java +++ b/ftp/src/test/java/akka/stream/alpakka/ftp/StrictHostCheckingSftpSourceTest.java @@ -15,16 +15,16 @@ import java.util.concurrent.CompletionStage; import java.util.function.Function; -public class StrictHostCheckingSftpSourceTest extends BaseSftpSupport implements CommonStageTest { +public class StrictHostCheckingSftpSourceTest extends BaseSftpSupport implements CommonFtpStageTest { @Test public void listFiles() throws Exception { - CommonStageTest.super.listFiles(); + CommonFtpStageTest.super.listFiles(); } @Test public void fromPath() throws Exception { - CommonStageTest.super.fromPath(); + CommonFtpStageTest.super.fromPath(); } public Source getBrowserSource(String basePath) throws Exception {