File: scripting.tcl

package info (click to toggle)
redis 5%3A8.0.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 21,920 kB
  • sloc: ansic: 217,146; tcl: 51,883; sh: 4,625; perl: 4,214; cpp: 3,568; python: 3,165; makefile: 2,055; ruby: 639; javascript: 30; csh: 7
file content (91 lines) | stat: -rw-r--r-- 3,828 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
start_cluster 1 0 {tags {external:skip cluster}} {

    test {Eval scripts with shebangs and functions default to no cross slots} {
        # Test that scripts with shebang block cross slot operations
        assert_error "ERR Script attempted to access keys that do not hash to the same slot*" {
            r 0 eval {#!lua
                redis.call('set', 'foo', 'bar')
                redis.call('set', 'bar', 'foo')
                return 'OK'
            } 0}

        # Test the functions by default block cross slot operations
        r 0 function load REPLACE {#!lua name=crossslot
            local function test_cross_slot(keys, args)
                redis.call('set', 'foo', 'bar')
                redis.call('set', 'bar', 'foo')
                return 'OK'
            end

            redis.register_function('test_cross_slot', test_cross_slot)}
        assert_error "ERR Script attempted to access keys that do not hash to the same slot*" {r FCALL test_cross_slot 0}
    }

    test {Cross slot commands are allowed by default for eval scripts and with allow-cross-slot-keys flag} {
        # Old style lua scripts are allowed to access cross slot operations
        r 0 eval "redis.call('set', 'foo', 'bar'); redis.call('set', 'bar', 'foo')" 0

        # scripts with allow-cross-slot-keys flag are allowed
        r 0 eval {#!lua flags=allow-cross-slot-keys
            redis.call('set', 'foo', 'bar'); redis.call('set', 'bar', 'foo')
        } 0

        # Retrieve data from different slot to verify data has been stored in the correct dictionary in cluster-enabled setup
        # during cross-slot operation from the above lua script.
        assert_equal "bar" [r 0 get foo]
        assert_equal "foo" [r 0 get bar]
        r 0 del foo
        r 0 del bar

        # Functions with allow-cross-slot-keys flag are allowed
        r 0 function load REPLACE {#!lua name=crossslot
            local function test_cross_slot(keys, args)
                redis.call('set', 'foo', 'bar')
                redis.call('set', 'bar', 'foo')
                return 'OK'
            end

            redis.register_function{function_name='test_cross_slot', callback=test_cross_slot, flags={ 'allow-cross-slot-keys' }}}
        r FCALL test_cross_slot 0

        # Retrieve data from different slot to verify data has been stored in the correct dictionary in cluster-enabled setup
        # during cross-slot operation from the above lua function.
        assert_equal "bar" [r 0 get foo]
        assert_equal "foo" [r 0 get bar]
    }
    
    test {Cross slot commands are also blocked if they disagree with pre-declared keys} {
        assert_error "ERR Script attempted to access keys that do not hash to the same slot*" {
            r 0 eval {#!lua
                redis.call('set', 'foo', 'bar')
                return 'OK'
            } 1 bar}
    }

    test {Cross slot commands are allowed by default if they disagree with pre-declared keys} {
        r 0 flushall
        r 0 eval "redis.call('set', 'foo', 'bar')" 1 bar

        # Make sure the script writes to the right slot
        assert_equal 1 [r 0 cluster COUNTKEYSINSLOT 12182] ;# foo slot
        assert_equal 0 [r 0 cluster COUNTKEYSINSLOT 5061] ;# bar slot
    }

    test "Function no-cluster flag" {
        R 0 function load {#!lua name=test
            redis.register_function{function_name='f1', callback=function() return 'hello' end, flags={'no-cluster'}}
        }
        catch {R 0 fcall f1 0} e
        assert_match {*Can not run script on cluster, 'no-cluster' flag is set*} $e
    }

    test "Script no-cluster flag" {
        catch {
            R 0 eval {#!lua flags=no-cluster
                return 1
            } 0
        } e
        
        assert_match {*Can not run script on cluster, 'no-cluster' flag is set*} $e
    }
}