<commit_before>/*
 * Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com)
 *
 * 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.rundeck.storage.conf

import org.rundeck.storage.data.DataUtil
import spock.lang.Specification
import org.rundeck.storage.data.MemoryTree

import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.data.DataUtil.dataWithText


/**
 * $INTERFACE is ...
 * User: greg
 * Date: 2/4/14
 * Time: 5:02 PM
 */
class TreeStackSpecification extends Specification {
    def "path check"() {
        given:
        def mem = new MemoryTree()
        def sub = new SubPathTree(mem, "test/path", true)
        expect:
        TreeStack.matchesPath(asPath("test/path"),sub)
        TreeStack.matchesPath(asPath("test/path/asdf"), sub)
        TreeStack.matchesPath(asPath("test/path/asdf/dxx"), sub)
        !TreeStack.matchesPath(asPath("test/asdf"), sub)
        !TreeStack.matchesPath(asPath("something/else"), sub)
    }
    def "parent path check"() {
        given:
        def mem = new MemoryTree()
        def sub = new SubPathTree(mem, "test/path", true)
        expect:
        TreeStack.hasParentPath(asPath("test"),sub)
        !TreeStack.hasParentPath(asPath("test/path"), sub)
        !TreeStack.hasParentPath(asPath("test/path/asdf"), sub)
        !TreeStack.hasParentPath(asPath("test/path/asdf/dxx"), sub)
        !TreeStack.hasParentPath(asPath("test/asdf"), sub)
        !TreeStack.hasParentPath(asPath("something/else"), sub)
    }
    def "tree handler handles sub tree resources"(){
        def mem1 = new MemoryTree()
        def sub1 = new SubPathTree(mem1, "/test1", true)
        def mem3 = new MemoryTree()
        def tree1 = new TreeStack([sub1], mem3)
        when:
        def res1=tree1.createResource("/test1/monkey", dataWithText('monkey data'))
        def res2 =tree1.createResource("/test1/monkey2/balogna/flea", dataWithText('monkey data'))
        def res3 =tree1.createResource("/test2/monkey", dataWithText('monkey2 data'))
        then:
        null!=res1
        res1.path.path=='test1/monkey'
        res2.path.path=='test1/monkey2/balogna/flea'
        res3.path.path=='test2/monkey'
        mem1.hasResource("/test1/monkey")
        mem1.hasResource("/test1/monkey2/balogna/flea")
        !mem1.hasResource("/test2/monkey")

        !mem3.hasResource("/test1/monkey2/balogna/flea")
        !mem3.hasResource("/test1/monkey")
        mem3.hasResource("/test2/monkey")
    }

    def "cannot define two handlers with the same path"() {
        def sub1 = new SubPathTree(memory(), "/test1", true)
        def sub2 = new SubPathTree(memory(), "/test1", true)

        when:
            def tree1 = new TreeStack([sub1, sub2], memory())
        then:
            IllegalArgumentException e = thrown()
    }

    public MemoryTree memory() {
        new MemoryTree()
    }

    @Unroll
    def "longest handler subpath has precedence"() {
        given:

            def mem1 = memory()
            def sub1 = new SubPathTree(mem1, orderA, true)

            def mem2 = memory()
            def sub2 = new SubPathTree(mem2, orderB, true)
            def mem3 = memory()
            def tree1 = new TreeStack([sub1, sub2], mem3)

            tree1.createResource(expectA, dataWithText('a data'))
            tree1.createResource(expectB, dataWithText('b data'))
        expect:
            mem1.hasResource(expectA)
            !mem2.hasResource(expectA)
            !mem1.hasResource(expectB)
            mem2.hasResource(expectB)

        where:
            orderA          | orderB          | expectA                       | expectB
            '/test1/monkey' | '/test1'        | "/test1/monkey/applesauce"    | '/test1/monkey2/balogna/flea'
            '/test1'        | '/test1/monkey' | '/test1/monkey2/balogna/flea' | "/test1/monkey/applesauce"
    }

    def "more specific subtree match"(){
        def mem1 = new MemoryTree()
        def sub1 = new SubPathTree(mem1, "/test1", true)
        def mem2 = new MemoryTree()<commit_msg>add test: create file with path of subdir<commit_after>/*
 * Copyright 2016 SimplifyOps, Inc. (http://simplifyops.com)
 *
 * 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.rundeck.storage.conf

import org.rundeck.storage.data.DataUtil
import spock.lang.Specification
import org.rundeck.storage.data.MemoryTree

import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.api.PathUtil.asPath
import static org.rundeck.storage.data.DataUtil.dataWithText


/**
 * $INTERFACE is ...
 * User: greg
 * Date: 2/4/14
 * Time: 5:02 PM
 */
class TreeStackSpecification extends Specification {
    def "path check"() {
        given:
        def mem = new MemoryTree()
        def sub = new SubPathTree(mem, "test/path", true)
        expect:
        TreeStack.matchesPath(asPath("test/path"),sub)
        TreeStack.matchesPath(asPath("test/path/asdf"), sub)
        TreeStack.matchesPath(asPath("test/path/asdf/dxx"), sub)
        !TreeStack.matchesPath(asPath("test/asdf"), sub)
        !TreeStack.matchesPath(asPath("something/else"), sub)
    }
    def "parent path check"() {
        given:
        def mem = new MemoryTree()
        def sub = new SubPathTree(mem, "test/path", true)
        expect:
        TreeStack.hasParentPath(asPath("test"),sub)
        !TreeStack.hasParentPath(asPath("test/path"), sub)
        !TreeStack.hasParentPath(asPath("test/path/asdf"), sub)
        !TreeStack.hasParentPath(asPath("test/path/asdf/dxx"), sub)
        !TreeStack.hasParentPath(asPath("test/asdf"), sub)
        !TreeStack.hasParentPath(asPath("something/else"), sub)
    }
    def "tree handler handles sub tree resources"(){
        def mem1 = new MemoryTree()
        def sub1 = new SubPathTree(mem1, "/test1", true)
        def mem3 = new MemoryTree()
        def tree1 = new TreeStack([sub1], mem3)
        when:
        def res1=tree1.createResource("/test1/monkey", dataWithText('monkey data'))
        def res2 =tree1.createResource("/test1/monkey2/balogna/flea", dataWithText('monkey data'))
        def res3 =tree1.createResource("/test2/monkey", dataWithText('monkey2 data'))
        then:
        null!=res1
        res1.path.path=='test1/monkey'
        res2.path.path=='test1/monkey2/balogna/flea'
        res3.path.path=='test2/monkey'
        mem1.hasResource("/test1/monkey")
        mem1.hasResource("/test1/monkey2/balogna/flea")
        !mem1.hasResource("/test2/monkey")

        !mem3.hasResource("/test1/monkey2/balogna/flea")
        !mem3.hasResource("/test1/monkey")
        mem3.hasResource("/test2/monkey")
    }

    def "cannot define two handlers with the same path"() {
        def sub1 = new SubPathTree(memory(), "/test1", true)
        def sub2 = new SubPathTree(memory(), "/test1", true)

        when:
            def tree1 = new TreeStack([sub1, sub2], memory())
        then:
            IllegalArgumentException e = thrown()
    }

    public MemoryTree memory() {
        new MemoryTree()
    }

    @Unroll
    def "longest handler subpath has precedence"() {
        given:

            def mem1 = memory()
            def sub1 = new SubPathTree(mem1, orderA, true)

            def mem2 = memory()
            def sub2 = new SubPathTree(mem2, orderB, true)
            def mem3 = memory()
            def tree1 = new TreeStack([sub1, sub2], mem3)

            tree1.createResource(expectA, dataWithText('a data'))
            tree1.createResource(expectB, dataWithText('b data'))
        expect:
            mem1.hasResource(expectA)
            !mem2.hasResource(expectA)
            !mem1.hasResource(expectB)
            mem2.hasResource(expectB)

        where:
            orderA          | orderB          | expectA                       | expectB
            '/test1/monkey' | '/test1'        | "/test1/monkey/applesauce"    | '/test1/monkey2/balogna/flea'
            '/test1'        | '/test1/monkey' | '/test1/monkey2/balogna/flea' | "/test1/monkey/applesauce"
    }


    def "create file in subtree root fails"() {
        def sub1 = new SubPathTree(new MemoryTree(), "/test1/monkey", false)
        def tree1 = new TreeStack([sub1], new MemoryTree())

        when:
            def result = tree1.createResource("/test1/monkey", dataWithText('monkey data'))

        then:
            IllegalArgumentException e = thrown()
    }

    def "more specific subtree match"(){
        def mem1 = new MemoryTree()
        def sub1 = new SubPathTree(mem1, "/test1", true)
        def mem2 = new MemoryTree()
{'fraction_non_alphanumeric': 0.12188979550720258, 'fraction_numerical': 0.01974413216480306, 'mean_word_length': 2.598405219282349, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4159997', 'n_tokens_mistral': 3121, 'n_tokens_neox': 3031, 'n_words': 720}