/*
 *  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 groovy

import groovy.bugs.TestSupport

class ForLoopTest extends gls.CompilableTestSupport {

    def x

    void testFinalParameterInForLoopIsAllowed() {
        // only 'final' should be allowed: other modifiers like 'synchronized' should be forbidden
        shouldNotCompile """
            def collection = ["a", "b", "c", "d", "e"]
            for (synchronized String letter in collection) { }            
        """

        // only 'final' allowed, and no additional modifier
        shouldNotCompile """
            def collection = ["a", "b", "c", "d", "e"]
            for (final synchronized String letter in collection) { }
        """

        shouldCompile """
            def collection = ["a", "b", "c", "d", "e"]
            for (final String letter in collection) { }
            for (final String letter : collection) { }
            for (final letter in collection) { }
            for (final letter : collection) { }
        """
    }

    void testRange() {
        x = 0

        for (i in 0..9) {
            x = x + i
        }

        assert x == 45
    }

    void testRangeWithType() {
        x = 0

        for (Integer i in 0..9) {
            assert i.getClass() == Integer
            x = x + i
        }

        assert x == 45
    }

    void testRangeWithJdk15StyleAndType() {
        x = 0

        for (Integer i: 0..9) {
            assert i.getClass() == Integer
            x = x + i
        }

        assert x == 45
    }

    void testList() {
        x = 0

        for (i in [0, 1, 2, 3, 4]) {
            x = x + i
        }

        assert x == 10
    }

    void testArray() {
        def array = (0..4).toArray()

        x = 0

        for (i in array) {
            x = x + i
        }

        assert x == 10
    }

    void testIntArray() {
        def array = TestSupport.getIntArray()

        x = 0

        for (i in array) {
            x = x + i
        }

        assert x == 15
    }

    void testString() {
        def text = "abc"

        def list = []
        for (c in text) {
            list.add(c)
        }

        assert list == ["a", "b", "c"]
    }

    void testVector() {
        def vector = new Vector()
        vector.addAll([1, 2, 3])

        def answer = []
        for (i in vector.elements()) {
            answer << i
        }
        assert answer == [1, 2, 3]
    }

    void testClassicFor() {
        def sum = 0
        for (int i = 0; i < 10; i++) {
            sum++
        }
        assert sum == 10

        def list = [1, 2]
        sum = 0
        for (Iterator i = list.iterator(); i.hasNext();) {
            sum += i.next()
        }
        assert sum == 3
    }

    void testClassicForNested() {
        def sum = 0
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 10; j++) {
                sum++
            }
        }
        assert sum == 100
    }

    void testClassicForWithContinue() {
        def sum1 = 0
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) continue
            sum1 += i
        }
        assert sum1 == 25

        // same as before, but with label
        def sum2 = 0
        test:
        for (int i = 0; i < 10; i++) {
            if (i % 2 == 0) continue test
            sum2 += i
        }
        assert sum2 == 25

    }

    void testClassicForWithEmptyInitializer() {
        def i = 0
        def sum1 = 0
        for (; i < 10; i++) {
            if (i % 2 == 0) continue
            sum1 += i
        }
        assert sum1 == 25
    }

    void testClassicForWithEmptyBody() {
        int i
        for (i = 0; i < 5; i++);
        assert i == 5
    }

    void testClassicForWithEverythingInitCondNextExpressionsEmpty() {
        int counter = 0
        for (;;) {
            counter++
            if (counter == 10) break
        }

        assert counter == 10, "The body of the for loop wasn't executed, it should have looped 10 times."
    }

}
