github.com/datastax/go-cassandra-native-protocol@v0.0.0-20220706104457-5e8aad05cf90/datacodec/math_test.go (about) 1 // Copyright 2021 DataStax 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package datacodec 16 17 import ( 18 "math" 19 "testing" 20 21 "github.com/stretchr/testify/assert" 22 ) 23 24 func Test_addExact(t *testing.T) { 25 tests := []struct { 26 name string 27 x int64 28 y int64 29 expected int64 30 overflow bool 31 }{ 32 {"zero", 0, 0, 0, false}, 33 {"positive", 1, 1, 2, false}, 34 {"negative", -1, -1, -2, false}, 35 36 {"max + zero", math.MaxInt64, 0, math.MaxInt64, false}, 37 {"zero + max", 0, math.MaxInt64, math.MaxInt64, false}, 38 {"max-1 + 1", math.MaxInt64 - 1, 1, math.MaxInt64, false}, 39 {"1 + max-1", 1, math.MaxInt64 - 1, math.MaxInt64, false}, 40 41 {"max + 1", math.MaxInt64, 1, 0, true}, 42 {"1 + max", 1, math.MaxInt64, 0, true}, 43 {"max-1 + 2", math.MaxInt64 - 1, 2, 0, true}, 44 {"2 + max-1", 2, math.MaxInt64 - 1, 0, true}, 45 46 {"min + zero", math.MinInt64, 0, math.MinInt64, false}, 47 {"zero + min", 0, math.MinInt64, math.MinInt64, false}, 48 {"min+1 + -1", math.MinInt64 + 1, -1, math.MinInt64, false}, 49 {"-1 + min+1", -1, math.MinInt64 + 1, math.MinInt64, false}, 50 51 {"min - 1", math.MinInt64, -1, 0, true}, 52 {"-1 + min", -1, math.MinInt64, 0, true}, 53 {"min+1 + -2", math.MinInt64 + 1, -2, 0, true}, 54 {"-2 + min+1", -2, math.MinInt64 + 1, 0, true}, 55 } 56 for _, tt := range tests { 57 t.Run(tt.name, func(t *testing.T) { 58 actual, overflow := addExact(tt.x, tt.y) 59 assert.Equal(t, tt.expected, actual) 60 assert.Equal(t, tt.overflow, overflow) 61 }) 62 } 63 } 64 65 func Test_multiplyExact(t *testing.T) { 66 tests := []struct { 67 name string 68 x int64 69 y int64 70 expected int64 71 overflow bool 72 }{ 73 {"0 * 0", 0, 0, 0, false}, 74 {"1 * 0", 1, 0, 0, false}, 75 {"0 * 1", 0, 1, 0, false}, 76 {"1 * 1", 1, 1, 1, false}, 77 {"-1 * -1", -1, -1, 1, false}, 78 {"-1 * 1", -1, 1, -1, false}, 79 {"1 * -1", 1, -1, -1, false}, 80 81 {"max/2 * 2", math.MaxInt64 / 2, 2, math.MaxInt64 - 1, false}, 82 {"2 * max/2", 2, math.MaxInt64 / 2, math.MaxInt64 - 1, false}, 83 {"max/2+1 * 2", math.MaxInt64/2 + 1, 2, 0, true}, 84 {"2 * max/2+1", 2, math.MaxInt64/2 + 1, 0, true}, 85 86 {"max * 0", math.MaxInt64, 0, 0, false}, 87 {"0 * max", 0, math.MaxInt64, 0, false}, 88 {"max * 1", math.MaxInt64, 1, math.MaxInt64, false}, 89 {"1 * max", 1, math.MaxInt64, math.MaxInt64, false}, 90 {"max * -1", math.MaxInt64, -1, -math.MaxInt64, false}, 91 {"-1 * max", -1, math.MaxInt64, -math.MaxInt64, false}, 92 {"max * 2", math.MaxInt64, 2, 0, true}, 93 {"2 * max", 2, math.MaxInt64, 0, true}, 94 {"max * -2", math.MaxInt64, -2, 0, true}, 95 {"-2 * max", -2, math.MaxInt64, 0, true}, 96 97 {"min/2 * 2", math.MinInt64 / 2, 2, math.MinInt64, false}, 98 {"2 * min/2", 2, math.MinInt64 / 2, math.MinInt64, false}, 99 {"min/2-1 * 2", math.MinInt64/2 - 1, 2, 0, true}, 100 {"2 * min/2-1", 2, math.MinInt64/2 - 1, 0, true}, 101 102 {"min * 0", math.MinInt64, 0, 0, false}, 103 {"0 * min", 0, math.MinInt64, 0, false}, 104 {"min * 1", math.MinInt64, 1, math.MinInt64, false}, 105 {"1 * min", 1, math.MinInt64, math.MinInt64, false}, 106 {"min * -1", math.MinInt64, -1, 0, true}, 107 {"-1 * min", -1, math.MinInt64, 0, true}, 108 {"min * 2", math.MinInt64, 2, 0, true}, 109 {"2 * min", 2, math.MinInt64, 0, true}, 110 {"min * -2", math.MinInt64, -2, 0, true}, 111 {"-2 * min", -2, math.MinInt64, 0, true}, 112 } 113 for _, tt := range tests { 114 t.Run(tt.name, func(t *testing.T) { 115 actual, overflow := multiplyExact(tt.x, tt.y) 116 assert.Equal(t, tt.expected, actual) 117 assert.Equal(t, tt.overflow, overflow) 118 }) 119 } 120 } 121 122 func Test_floorDiv(t *testing.T) { 123 tests := []struct { 124 name string 125 x int64 126 y int64 127 expected int64 128 }{ 129 {"0/1", 0, 1, 0}, 130 {"0/-1", 0, -1, 0}, 131 {"1/1", 1, 1, 1}, 132 {"1/-1", 1, -1, -1}, 133 {"2/2", 2, 2, 1}, 134 {"2/-2", 2, -2, -1}, 135 {"3/2", 3, 2, 1}, 136 {"3/-2", 3, -2, -2}, 137 {"-1/1", -1, 1, -1}, 138 {"-1/-1", -1, -1, 1}, 139 {"-2/2", -2, 2, -1}, 140 {"-2/-2", -2, -2, 1}, 141 {"-3/2", -3, 2, -2}, 142 {"-3/-2", -3, -2, 1}, 143 144 {"5/2", 5, 2, 2}, 145 {"5/-2", 5, -2, -3}, 146 {"-5/2", -5, 2, -3}, 147 {"-5/-2", -5, -2, 2}, 148 149 {"1/min", 1, math.MinInt64, -1}, 150 {"-1/min", -1, math.MinInt64, 0}, 151 {"1/max", 1, math.MaxInt64, 0}, 152 {"-1/max", -1, math.MaxInt64, -1}, 153 154 {"min/1", math.MinInt64, 1, math.MinInt64}, 155 {"min/-1", math.MinInt64, -1, math.MinInt64}, // overflow: math.MaxInt64+1 156 {"max/1", math.MaxInt64, 1, math.MaxInt64}, 157 {"max/-1", math.MaxInt64, -1, -math.MaxInt64}, 158 } 159 for _, tt := range tests { 160 t.Run(tt.name, func(t *testing.T) { 161 actual := floorDiv(tt.x, tt.y) 162 assert.Equal(t, tt.expected, actual) 163 }) 164 } 165 } 166 167 func Test_floorMod(t *testing.T) { 168 tests := []struct { 169 name string 170 x int64 171 y int64 172 expected int64 173 }{ 174 {"0/1", 0, 1, 0}, 175 {"0/-1", 0, -1, 0}, 176 {"1/1", 1, 1, 0}, 177 {"1/-1", 1, -1, 0}, 178 {"2/2", 2, 2, 0}, 179 {"2/-2", 2, -2, 0}, 180 {"3/2", 3, 2, 1}, 181 {"3/-2", 3, -2, -1}, 182 {"-1/1", -1, 1, 0}, 183 {"-1/-1", -1, -1, 0}, 184 {"-2/2", -2, 2, -0}, 185 {"-2/-2", -2, -2, 0}, 186 {"-3/2", -3, 2, 1}, 187 {"-3/-2", -3, -2, -1}, 188 189 {"5/2", 5, 2, 1}, 190 {"5/-2", 5, -2, -1}, 191 {"-5/2", -5, 2, 1}, 192 {"-5/-2", -5, -2, -1}, 193 194 {"1/min", 1, math.MinInt64, 1 + math.MinInt64}, // overflow 195 {"-1/min", -1, math.MinInt64, -1}, 196 {"1/max", 1, math.MaxInt64, 1}, 197 {"-1/max", -1, math.MaxInt64, -1 + math.MaxInt64}, 198 199 {"min/1", math.MinInt64, 1, 0}, 200 {"min/-1", math.MinInt64, -1, 0}, 201 {"max/1", math.MaxInt64, 1, 0}, 202 {"max/-1", math.MaxInt64, -1, 0}, 203 } 204 for _, tt := range tests { 205 t.Run(tt.name, func(t *testing.T) { 206 actual := floorMod(tt.x, tt.y) 207 assert.Equal(t, tt.expected, actual) 208 }) 209 } 210 }