blob: 43ad8a8d6be8d64f815e3b1100e878253b6956cf [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package org.apache.toree.kernel.api
import java.io.{InputStream, PrintStream}
import com.typesafe.config.Config
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.toree.boot.layer.InterpreterManager
import org.apache.toree.comm.CommManager
import org.apache.toree.global.ExecuteRequestState
import org.apache.toree.interpreter._
import org.apache.toree.kernel.protocol.v5._
import org.apache.toree.kernel.protocol.v5.kernel.ActorLoader
import org.apache.toree.plugins.PluginManager
import org.mockito.Mockito._
import org.scalatest.mock.MockitoSugar
import org.scalatest.{BeforeAndAfter, FunSpec, Matchers}
class KernelSpec extends FunSpec with Matchers with MockitoSugar
with BeforeAndAfter
{
private val BadCode = Some("abc foo bar")
private val GoodCode = Some("val foo = 1")
private val ErrorCode = Some("val foo = bar")
private val ErrorMsg = "Name: error\n" +
"Message: bad\n" +
"StackTrace: 1"
private var mockConfig: Config = _
private var mockSparkContext: SparkContext = _
private var mockSparkConf: SparkConf = _
private var mockActorLoader: ActorLoader = _
private var mockInterpreter: Interpreter = _
private var mockInterpreterManager: InterpreterManager = _
private var mockCommManager: CommManager = _
private var mockPluginManager: PluginManager = _
private var kernel: Kernel = _
private var spyKernel: Kernel = _
before {
mockConfig = mock[Config]
mockInterpreter = mock[Interpreter]
mockInterpreterManager = mock[InterpreterManager]
mockSparkContext = mock[SparkContext]
mockSparkConf = mock[SparkConf]
mockPluginManager = mock[PluginManager]
when(mockInterpreterManager.defaultInterpreter)
.thenReturn(Some(mockInterpreter))
when(mockInterpreterManager.interpreters)
.thenReturn(Map[String, org.apache.toree.interpreter.Interpreter]())
when(mockInterpreter.interpret(BadCode.get))
.thenReturn((Results.Incomplete, null))
when(mockInterpreter.interpret(GoodCode.get))
.thenReturn((Results.Success, Left(Map("text/plain" -> "ok"))))
when(mockInterpreter.interpret(ErrorCode.get))
.thenReturn((Results.Error, Right(ExecuteError("error","bad", List("1")))))
mockCommManager = mock[CommManager]
mockActorLoader = mock[ActorLoader]
kernel = new Kernel(
mockConfig, mockActorLoader, mockInterpreterManager, mockCommManager,
mockPluginManager
)
spyKernel = spy(kernel)
}
after {
ExecuteRequestState.reset()
}
describe("Kernel") {
describe("#eval") {
it("should return syntax error") {
kernel eval BadCode should be((false, Map("text/plain" -> "Syntax Error!")))
}
it("should return ok") {
kernel eval GoodCode should be((true, Map("text/plain" -> "ok")))
}
it("should return error") {
kernel eval ErrorCode should be((false, Map("text/plain" -> ErrorMsg)))
}
it("should return error on None") {
kernel eval None should be ((false, Map("text/plain" -> "Error!")))
}
}
describe("#out") {
it("should throw an exception if the ExecuteRequestState has not been set") {
intercept[IllegalArgumentException] {
kernel.out
}
}
it("should create a new PrintStream instance if the ExecuteRequestState has been set") {
ExecuteRequestState.processIncomingKernelMessage(
new KernelMessage(Nil, "", mock[Header], mock[ParentHeader],
mock[Metadata], "")
)
kernel.out shouldBe a [PrintStream]
}
}
describe("#err") {
it("should throw an exception if the ExecuteRequestState has not been set") {
intercept[IllegalArgumentException] {
kernel.err
}
}
it("should create a new PrintStream instance if the ExecuteRequestState has been set") {
ExecuteRequestState.processIncomingKernelMessage(
new KernelMessage(Nil, "", mock[Header], mock[ParentHeader],
mock[Metadata], "")
)
// TODO: Access the underlying streamType field to assert stderr?
kernel.err shouldBe a [PrintStream]
}
}
describe("#in") {
it("should throw an exception if the ExecuteRequestState has not been set") {
intercept[IllegalArgumentException] {
kernel.in
}
}
it("should create a new InputStream instance if the ExecuteRequestState has been set") {
ExecuteRequestState.processIncomingKernelMessage(
new KernelMessage(Nil, "", mock[Header], mock[ParentHeader],
mock[Metadata], "")
)
kernel.in shouldBe a [InputStream]
}
}
describe("#stream") {
it("should throw an exception if the ExecuteRequestState has not been set") {
intercept[IllegalArgumentException] {
kernel.stream
}
}
it("should create a StreamMethods instance if the ExecuteRequestState has been set") {
ExecuteRequestState.processIncomingKernelMessage(
new KernelMessage(Nil, "", mock[Header], mock[ParentHeader],
mock[Metadata], "")
)
kernel.stream shouldBe a [StreamMethods]
}
}
describe("#display") {
it("should throw an exception if the ExecuteRequestState has not been set") {
intercept[IllegalArgumentException] {
kernel.display
}
}
it("should create a DisplayMethods instance if the ExecuteRequestState has been set") {
ExecuteRequestState.processIncomingKernelMessage(
new KernelMessage(Nil, "", mock[Header], mock[ParentHeader],
mock[Metadata], "")
)
kernel.display shouldBe a [DisplayMethods]
}
}
describe("when spark.master is set in config") {
it("should create SparkConf") {
val expected = "some value"
doReturn(expected).when(mockConfig).getString("spark.master")
val sparkConf = kernel.createSparkConf(new SparkConf().setMaster(expected))
sparkConf.get("spark.master") should be (expected)
}
}
}
}