pekko/akka-stream-tests/src/test/scala/akka/stream/io/FileSinkSpec.scala

146 lines
4.9 KiB
Scala

/**
* Copyright (C) 2015 Typesafe Inc. <http://www.typesafe.com>
*/
package akka.stream.io
import java.io.File
import akka.actor.ActorSystem
import akka.stream.impl.ActorMaterializerImpl
import akka.stream.impl.StreamSupervisor
import akka.stream.impl.StreamSupervisor.Children
import akka.stream.scaladsl.{ FileIO, Sink, Source }
import akka.stream.testkit._
import akka.stream.testkit.Utils._
import akka.stream.testkit.StreamTestKit
import akka.stream.ActorMaterializer
import akka.stream.ActorMaterializerSettings
import akka.stream.ActorAttributes
import akka.util.ByteString
import akka.util.Timeout
import scala.collection.mutable.ListBuffer
import scala.concurrent.Await
import scala.concurrent.duration._
class FileSinkSpec extends AkkaSpec(UnboundedMailboxConfig) {
val settings = ActorMaterializerSettings(system).withDispatcher("akka.actor.default-dispatcher")
implicit val materializer = ActorMaterializer(settings)
val TestLines = {
val b = ListBuffer[String]()
b.append("a" * 1000 + "\n")
b.append("b" * 1000 + "\n")
b.append("c" * 1000 + "\n")
b.append("d" * 1000 + "\n")
b.append("e" * 1000 + "\n")
b.append("f" * 1000 + "\n")
b.toList
}
val TestByteStrings = TestLines.map(ByteString(_))
"SynchronousFile Sink" must {
"write lines to a file" in assertAllStagesStopped {
targetFile { f
val completion = Source(TestByteStrings)
.runWith(FileIO.toFile(f))
val size = Await.result(completion, 3.seconds)
size should equal(6006)
checkFileContents(f, TestLines.mkString(""))
}
}
"by default write into existing file" in assertAllStagesStopped {
targetFile { f
def write(lines: List[String]) =
Source(lines)
.map(ByteString(_))
.runWith(FileIO.toFile(f))
val completion1 = write(TestLines)
Await.result(completion1, 3.seconds)
val lastWrite = List("x" * 100)
val completion2 = write(lastWrite)
val written2 = Await.result(completion2, 3.seconds)
written2 should ===(lastWrite.flatten.length)
checkFileContents(f, lastWrite.mkString("") + TestLines.mkString("").drop(100))
}
}
"allow appending to file" in assertAllStagesStopped {
targetFile { f
def write(lines: List[String] = TestLines) =
Source(lines)
.map(ByteString(_))
.runWith(FileIO.toFile(f, append = true))
val completion1 = write()
val written1 = Await.result(completion1, 3.seconds)
val lastWrite = List("x" * 100)
val completion2 = write(lastWrite)
val written2 = Await.result(completion2, 3.seconds)
f.length() should ===(written1 + written2)
checkFileContents(f, TestLines.mkString("") + lastWrite.mkString("") + "\n")
}
}
"use dedicated blocking-io-dispatcher by default" in assertAllStagesStopped {
targetFile { f
val sys = ActorSystem("dispatcher-testing", UnboundedMailboxConfig)
val materializer = ActorMaterializer()(sys)
implicit val timeout = Timeout(3.seconds)
try {
Source.fromIterator(() Iterator.continually(TestByteStrings.head)).runWith(FileIO.toFile(f))(materializer)
materializer.asInstanceOf[ActorMaterializerImpl].supervisor.tell(StreamSupervisor.GetChildren, testActor)
val ref = expectMsgType[Children].children.find(_.path.toString contains "fileSource").get
assertDispatcher(ref, "akka.stream.default-blocking-io-dispatcher")
} finally shutdown(sys)
}
}
// FIXME: overriding dispatcher should be made available with dispatcher alias support in materializer (#17929)
"allow overriding the dispatcher using Attributes" in assertAllStagesStopped {
pending
targetFile { f
val sys = ActorSystem("dispatcher-testing", UnboundedMailboxConfig)
val materializer = ActorMaterializer()(sys)
implicit val timeout = Timeout(3.seconds)
try {
Source.fromIterator(() Iterator.continually(TestByteStrings.head))
.to(FileIO.toFile(f))
.withAttributes(ActorAttributes.dispatcher("akka.actor.default-dispatcher"))
.run()(materializer)
materializer.asInstanceOf[ActorMaterializerImpl].supervisor.tell(StreamSupervisor.GetChildren, testActor)
val ref = expectMsgType[Children].children.find(_.path.toString contains "File").get
assertDispatcher(ref, "akka.actor.default-dispatcher")
} finally shutdown(sys)
}
}
}
private def targetFile(block: File Unit) {
val targetFile = File.createTempFile("synchronous-file-sink", ".tmp")
try block(targetFile) finally targetFile.delete()
}
def checkFileContents(f: File, contents: String): Unit = {
val s = scala.io.Source.fromFile(f)
val out = s.getLines().mkString("\n") + "\n"
s.close()
out should ===(contents)
}
}