/*
 * Copyright 2009 the original author or authors.
 *
 * Licensed 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.spockframework.smoke

import spock.lang.FailsWith
import spock.lang.Specification
import spock.lang.Issue
import org.spockframework.EmbeddedSpecification
import org.codehaus.groovy.runtime.typehandling.GroovyCastException

class CleanupBlocks extends EmbeddedSpecification {
  def "basic usage"() {
    def x
    setup: x = 1
    expect: x == 1
    cleanup: x = 0
  }

  def "may access all previously defined local vars"() {
    def a

    setup:
    def b
    when:
    String c
    then:
    List d

    cleanup:
    a = 0
    b = 0
    c = ""
    d = null
  }

  @FailsWith(IllegalArgumentException)
  def "is executed if no exception is thrown"() {
    def a = 1

    cleanup:
    a = 0
    if (a == 0) throw new IllegalArgumentException()
  }

  @FailsWith(IllegalArgumentException)
  def "is executed if exception is thrown"() {
    def a = 1
    throw new Exception()

    cleanup:
    a = 0
    if (a == 0) throw new IllegalArgumentException()
  }

  @FailsWith(IllegalArgumentException)
  def "if exception is thrown, code between occurrence of exception and cleanup-block is not executed"() {
    def a = 1
    throw new IllegalArgumentException()
    a = 2

    cleanup:
    assert a == 1
  }

  @Issue("http://issues.spockframework.org/detail?id=266")
  def "variable with primitive type can be declared in presence of cleanup-block"() {
    int x = 1

    expect:
    x == 1

    cleanup:
    []
  }

  def "variable with primitive type can be read in cleanup-block"() {
    int x = 1

    cleanup:
    assert x == 1
  }

  @FailsWith(GroovyCastException)
  def "declared type of variable is kept"() {
    int x = "abc"

    cleanup:
    []
  }

  @Issue("http://issues.spockframework.org/detail?id=371")
  def "multi-declaration with primitive type in presence of cleanup-block"() {
    when:
    def (String foo, int bar) = ["foo", 42]

    then:
    foo == "foo"
    bar == 42

    cleanup:
    assert foo == "foo"
    assert bar == 42
  }

  // TODO: doesn't work for char
  def "multi-declaration with all primitive types in presence of cleanup-block"() {
    setup:
    def (byte b, int i, long l, float f, double d, boolean bool) =
    [(byte) 1, 1, 1l, 1f, 1d, true]

    expect:
    b == (byte) 1
    i == 1
    l == 1l
    f == 1f
    d == 1d
    bool

    cleanup:
    assert b == (byte) 1
    assert i == 1
    assert l == 1l
    assert f == 1f
    assert d == 1d
    assert bool
  }
}
