TtlRecursiveTaskTest.kt 5.8 KB
Newer Older
1 2
package com.alibaba.ttl.forkjoin.recursive_task

oldratlee's avatar
oldratlee 已提交
3 4
import com.alibaba.*
import com.alibaba.support.junit.conditional.BelowJava7
5 6 7 8 9
import com.alibaba.support.junit.conditional.ConditionalIgnoreRule
import com.alibaba.support.junit.conditional.ConditionalIgnoreRule.ConditionalIgnore
import com.alibaba.ttl.TransmittableThreadLocal
import com.alibaba.ttl.TtlRecursiveTask
import org.junit.AfterClass
oldratlee's avatar
oldratlee 已提交
10 11 12
import org.junit.Assert.assertEquals
import org.junit.Assert.fail
import org.junit.Rule
13
import org.junit.Test
oldratlee's avatar
oldratlee 已提交
14
import java.util.concurrent.*
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41

private val pool = ForkJoinPool()
private val singleThreadPool = ForkJoinPool(1)

/**
 * @author LNAmp
 * @author Jerry Lee (oldratlee at gmail dot com)
 */
class TtlRecursiveTaskTest {
    @Rule
    @JvmField
    val rule = ConditionalIgnoreRule()

    @Test
    @ConditionalIgnore(condition = BelowJava7::class)
    fun test_TtlRecursiveTask_asyncWith_ForkJoinPool() {
        run_test_with_pool(pool)
    }

    @Test
    @ConditionalIgnore(condition = BelowJava7::class)
    fun test_TtlRecursiveTask_asyncWith_SingleThreadForkJoinPool() {
        run_test_with_pool(singleThreadPool)
    }
}

private fun run_test_with_pool(forkJoinPool: ForkJoinPool) {
oldratlee's avatar
oldratlee 已提交
42
    val ttlInstances = createParentTtlInstances()
43 44

    val numbers = 0..42
oldratlee's avatar
oldratlee 已提交
45
    val sumTask: ForkJoinTask<Int> = if (noTtlAgentRun()) TtlSumTask(numbers, ttlInstances) else SumTask(numbers, ttlInstances)
46

oldratlee's avatar
oldratlee 已提交
47 48 49
    // create after new Task, won't see parent value in in task!
    createParentTtlInstancesAfterCreateChild(ttlInstances)

50 51 52 53 54

    val future = forkJoinPool.submit(sumTask)
    assertEquals(numbers.sum(), future.get())

    // child Inheritable
oldratlee's avatar
oldratlee 已提交
55 56 57
    assertTtlValues(
            mapOf(PARENT_CREATE_UNMODIFIED_IN_CHILD to PARENT_CREATE_UNMODIFIED_IN_CHILD,
                    PARENT_CREATE_MODIFIED_IN_CHILD to PARENT_CREATE_MODIFIED_IN_CHILD /* Not change*/),
oldratlee's avatar
oldratlee 已提交
58
            (sumTask as Getter).getcopied()
59 60 61
    )

    // left grand Task Inheritable, changed value
oldratlee's avatar
oldratlee 已提交
62 63
    assertTtlValues(
            mapOf(PARENT_CREATE_UNMODIFIED_IN_CHILD to PARENT_CREATE_UNMODIFIED_IN_CHILD,
oldratlee's avatar
oldratlee 已提交
64 65
                    PARENT_CREATE_MODIFIED_IN_CHILD to PARENT_CREATE_MODIFIED_IN_CHILD + CHANGE_POSTFIX /* CHANGED */),
            sumTask.getLeftSubTask().getcopied()
66 67 68
    )

    // right grand Task Inheritable, not change value
oldratlee's avatar
oldratlee 已提交
69 70 71
    assertTtlValues(
            mapOf(PARENT_CREATE_UNMODIFIED_IN_CHILD to PARENT_CREATE_UNMODIFIED_IN_CHILD,
                    PARENT_CREATE_MODIFIED_IN_CHILD to PARENT_CREATE_MODIFIED_IN_CHILD /* Not change*/),
oldratlee's avatar
oldratlee 已提交
72
            sumTask.getRightSubTask().getcopied()
73 74 75
    )

    // child do not effect parent
oldratlee's avatar
oldratlee 已提交
76 77 78 79 80
    assertTtlValues(
            mapOf(PARENT_CREATE_UNMODIFIED_IN_CHILD to PARENT_CREATE_UNMODIFIED_IN_CHILD,
                    PARENT_CREATE_MODIFIED_IN_CHILD to PARENT_CREATE_MODIFIED_IN_CHILD,
                    PARENT_CREATE_AFTER_CREATE_CHILD to PARENT_CREATE_AFTER_CREATE_CHILD),
            copyTtlValues(ttlInstances)
81 82 83 84
    )
}


oldratlee's avatar
oldratlee 已提交
85 86 87 88 89 90
private interface Getter {
    fun getcopied(): Map<String, Any>
    fun getLeftSubTask(): Getter
    fun getRightSubTask(): Getter
}

91 92 93 94 95 96
/**
 * A test demo class
 *
 * @author LNAmp
 * @see com.alibaba.ttl.TtlRecursiveTask
 */
oldratlee's avatar
oldratlee 已提交
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
private open class TtlSumTask(private val numbers: IntRange,
                              private val ttlMap: ConcurrentMap<String, TransmittableThreadLocal<String>>, private val changeTtlValue: Boolean = false) : TtlRecursiveTask<Int>(), Getter {

    lateinit var copied: Map<String, Any>
    lateinit var leftSubTask: TtlSumTask
    lateinit var rightSubTask: TtlSumTask

    override fun compute(): Int {
        if (changeTtlValue) {
            modifyParentTtlInstances(CHANGE_POSTFIX, ttlMap)
        }

        try {
            return if (numbers.count() <= 10) {
                numbers.sum()
            } else {
                val mid = numbers.start + numbers.count() / 2

                // left -> change! right -> not change.
                val left = TtlSumTask(numbers.start until mid, ttlMap, true)
                val right = TtlSumTask(mid..numbers.endInclusive, ttlMap, false)
                this.leftSubTask = left
                this.rightSubTask = right

                left.fork()
                right.fork()
                left.join() + right.join()
            }
        } finally {
            this.copied = copyTtlValues(this.ttlMap)
        }
    }

    override fun getcopied(): Map<String, Any> = copied

    override fun getLeftSubTask(): Getter = leftSubTask

    override fun getRightSubTask(): Getter = rightSubTask
}


/**
 * A test demo class
 */
oldratlee's avatar
oldratlee 已提交
141
private class SumTask(private val numbers: IntRange,
oldratlee's avatar
oldratlee 已提交
142
                      private val ttlMap: ConcurrentMap<String, TransmittableThreadLocal<String>>, private val changeTtlValue: Boolean = false) : RecursiveTask<Int>(), Getter {
143 144 145 146 147

    lateinit var copied: Map<String, Any>
    lateinit var leftSubTask: SumTask
    lateinit var rightSubTask: SumTask

oldratlee's avatar
oldratlee 已提交
148
    override fun compute(): Int {
149
        if (changeTtlValue) {
oldratlee's avatar
oldratlee 已提交
150
            modifyParentTtlInstances(CHANGE_POSTFIX, ttlMap)
151 152 153
        }

        try {
oldratlee's avatar
oldratlee 已提交
154
            return if (numbers.count() <= 10) {
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
                numbers.sum()
            } else {
                val mid = numbers.start + numbers.count() / 2

                // left -> change! right -> not change.
                val left = SumTask(numbers.start until mid, ttlMap, true)
                val right = SumTask(mid..numbers.endInclusive, ttlMap, false)
                this.leftSubTask = left
                this.rightSubTask = right

                left.fork()
                right.fork()
                left.join() + right.join()
            }
        } finally {
oldratlee's avatar
oldratlee 已提交
170
            this.copied = copyTtlValues(this.ttlMap)
171 172 173
        }
    }

oldratlee's avatar
oldratlee 已提交
174 175 176 177 178
    override fun getcopied(): Map<String, Any> = copied

    override fun getLeftSubTask(): Getter = leftSubTask

    override fun getRightSubTask(): Getter = rightSubTask
179
}
oldratlee's avatar
oldratlee 已提交
180 181

const val CHANGE_POSTFIX = " + 1"