sequel-sequence 0.4.0 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -31,4 +31,9 @@ module MysqlTestHelper
31
31
 
32
32
  Class.new(migration_class, &block).new(MysqlDB)
33
33
  end
34
+
35
+ def sequence_table_exists?(name)
36
+ table_list = MysqlDB.fetch('SHOW TABLES;').all.map { |_key, value| value }
37
+ table_list.include?(name)
38
+ end
34
39
  end
@@ -13,8 +13,10 @@ PostgresqlDB = Sequel.connect(
13
13
 
14
14
  module PostgresqlTestHelper
15
15
  def recreate_table
16
- PostgresqlDB.run 'DROP TABLE IF EXISTS things'
16
+ PostgresqlDB.run 'DROP TABLE IF EXISTS masters'
17
17
  PostgresqlDB.run 'DROP SEQUENCE IF EXISTS position'
18
+ PostgresqlDB.run 'DROP SEQUENCE IF EXISTS position_id'
19
+ PostgresqlDB.run 'DROP TABLE IF EXISTS things'
18
20
  PostgresqlDB.run 'DROP SEQUENCE IF EXISTS a'
19
21
  PostgresqlDB.run 'DROP SEQUENCE IF EXISTS b'
20
22
  PostgresqlDB.run 'DROP SEQUENCE IF EXISTS c'
@@ -72,40 +72,77 @@ class MariadbSequenceTest < Minitest::Test
72
72
  assert_equal 3, MariaDB.nextval(:position)
73
73
  end
74
74
 
75
- test "returns current/last sequence value, which doesn't increase by itself" do
75
+ test %( returns current/last sequence value, which doesn't increase by itself
76
+ for migration WITHOUT 'start' or 'increment' values ) do
76
77
  with_migration do
77
78
  def up
78
79
  create_sequence :position
79
80
  end
80
81
  end.up
81
82
 
82
- MariaDB.nextval(:position)
83
-
84
- assert_equal 1, MariaDB.currval(:position)
85
- assert_equal 1, MariaDB.lastval(:position)
86
83
  assert_equal 1, MariaDB.currval(:position)
87
84
  assert_equal 1, MariaDB.lastval(:position)
85
+
86
+ MariaDB.nextval(:position)
87
+
88
+ assert_equal 2, MariaDB.currval(:position)
89
+ assert_equal 2, MariaDB.lastval(:position)
88
90
  end
89
91
 
90
- test 'sets sequence value' do
92
+ test %( returns current/last sequence value, which doesn't increase by itself
93
+ for migration WITH 'start' and 'increment' values ) do
91
94
  with_migration do
92
95
  def up
93
- create_sequence :position
96
+ create_sequence :position, start: 2, increment: 3
94
97
  end
95
98
  end.up
96
99
 
100
+ assert_equal 2, MariaDB.currval(:position)
101
+ assert_equal 2, MariaDB.lastval(:position)
102
+
97
103
  MariaDB.nextval(:position)
104
+
105
+ assert_equal 5, MariaDB.currval(:position)
106
+ assert_equal 5, MariaDB.lastval(:position)
107
+ end
108
+
109
+ test 'sets a new sequence value greater than the current one' do
110
+ with_migration do
111
+ def up
112
+ create_sequence :position
113
+ end
114
+ end.up
115
+
98
116
  assert_equal MariaDB.currval(:position), 1
99
117
 
100
118
  MariaDB.setval(:position, 101)
101
- # in MariaDB, 'lastval' only works after 'nextval' rather than 'setval'
102
- assert_equal 1, MariaDB.lastval(:position)
119
+ # assert_equal 1, MariaDB.lastval(:position)
120
+ # we observe the modified behavior of the method
121
+ assert_equal 101, MariaDB.lastval(:position)
103
122
 
104
123
  MariaDB.nextval(:position)
105
- # now the value is correct
124
+ # the value is correct in any case
106
125
  assert_equal 102, MariaDB.lastval(:position)
107
126
  end
108
127
 
128
+ test 'sets a new sequence value less than the current one (does not change the value)' do
129
+ with_migration do
130
+ def up
131
+ create_sequence :position, start: 100
132
+ end
133
+ end.up
134
+
135
+ assert_equal MariaDB.currval(:position), 100
136
+
137
+ MariaDB.nextval(:position)
138
+ assert_equal MariaDB.currval(:position), 101
139
+
140
+ MariaDB.setval(:position, 1)
141
+ assert_equal 101, MariaDB.lastval(:position)
142
+
143
+ assert_equal 102, MariaDB.nextval(:position)
144
+ end
145
+
109
146
  test 'drops sequence and check_sequences' do
110
147
  with_migration do
111
148
  def up
@@ -125,14 +162,18 @@ class MariadbSequenceTest < Minitest::Test
125
162
  end
126
163
  end.down
127
164
 
128
- sequence = MariaDB.check_sequences.find do |seq|
129
- seq[:Tables_in_test] == 'position'
130
- end
165
+ sequence = MariaDB.check_sequences
131
166
 
132
- assert_nil sequence
167
+ assert_equal 0, sequence.size
133
168
  end
134
169
 
135
170
  test 'orders sequences' do
171
+ with_migration do
172
+ def up
173
+ drop_table :wares, if_exists: true
174
+ end
175
+ end.up
176
+
136
177
  list = MariaDB.check_sequences.map { |s| s[:Tables_in_test] }
137
178
  assert !list.include?('a')
138
179
  assert !list.include?('b')
@@ -140,7 +181,6 @@ class MariadbSequenceTest < Minitest::Test
140
181
 
141
182
  with_migration do
142
183
  def up
143
- drop_table :things, if_exists: true
144
184
  create_sequence :c
145
185
  create_sequence :a
146
186
  create_sequence :b
@@ -153,10 +193,21 @@ class MariadbSequenceTest < Minitest::Test
153
193
  assert list.include?('c')
154
194
  end
155
195
 
196
+ test 'checks custom sequence generated from code' do
197
+ assert_equal MariaDB.custom_sequence?(:c), false
198
+
199
+ with_migration do
200
+ def up
201
+ create_sequence :c
202
+ end
203
+ end.up
204
+
205
+ assert_equal MariaDB.custom_sequence?(:c), true
206
+ end
207
+
156
208
  test 'creates table that references sequence' do
157
209
  with_migration do
158
210
  def up
159
- drop_table :builders, if_exists: true
160
211
  create_sequence :position_id, if_exists: false, start: 1
161
212
  create_table :builders do
162
213
  primary_key :id
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'mock_test_helper'
4
+
5
+ class MockSequenceTest < Minitest::Test
6
+ test 'checks check_options with params' do
7
+ mocked_method = Minitest::Mock.new
8
+ some_instance = MockDB
9
+
10
+ mocked_method.expect :call, true, [Sequel::Database::DANGER_OPT_INCREMENT]
11
+ some_instance.stub :log_info, mocked_method do
12
+ some_instance.check_options({ increment: 2 })
13
+ end
14
+ mocked_method.verify
15
+
16
+ mocked_method.expect :call, true, [Sequel::Database::DANGER_OPT_INCREMENT]
17
+ some_instance.stub :log_info, mocked_method do
18
+ some_instance.check_options({ step: 2 })
19
+ end
20
+ mocked_method.verify
21
+ end
22
+
23
+ test 'checks custom_sequence?' do
24
+ assert_raises Sequel::MethodNotAllowed do
25
+ MockDB.custom_sequence?(:position)
26
+ end
27
+ end
28
+
29
+ test 'checks check_sequences' do
30
+ assert_raises Sequel::MethodNotAllowed do
31
+ MockDB.check_sequences
32
+ end
33
+ end
34
+
35
+ test 'checks create_sequence' do
36
+ assert_raises Sequel::MethodNotAllowed do
37
+ MockDB.create_sequence(:position)
38
+ end
39
+ end
40
+
41
+ test 'checks drop_sequence' do
42
+ assert_raises Sequel::MethodNotAllowed do
43
+ MockDB.drop_sequence(:position)
44
+ end
45
+ end
46
+
47
+ test 'checks quote_name' do
48
+ assert_raises Sequel::MethodNotAllowed do
49
+ MockDB.quote_name(:position)
50
+ end
51
+ end
52
+
53
+ test 'checks quote' do
54
+ assert_raises Sequel::MethodNotAllowed do
55
+ MockDB.quote(:position)
56
+ end
57
+ end
58
+
59
+ test 'checks nextval_with_label' do
60
+ assert_raises Sequel::MethodNotAllowed do
61
+ MockDB.nextval_with_label(:position, 100)
62
+ end
63
+ end
64
+
65
+ test 'checks nextval' do
66
+ assert_raises Sequel::MethodNotAllowed do
67
+ MockDB.nextval(:position)
68
+ end
69
+ end
70
+
71
+ test 'checks currval' do
72
+ assert_raises Sequel::MethodNotAllowed do
73
+ MockDB.currval(:position)
74
+ end
75
+ end
76
+
77
+ test 'checks lastval' do
78
+ assert_raises Sequel::MethodNotAllowed do
79
+ MockDB.lastval(:position)
80
+ end
81
+ end
82
+
83
+ test 'checks setval' do
84
+ assert_raises Sequel::MethodNotAllowed do
85
+ MockDB.setval(:position, 100)
86
+ end
87
+ end
88
+
89
+ test 'checks build_exists_condition for a true condition' do
90
+ assert_equal Sequel::Database::IF_EXISTS, MockDB.build_exists_condition(true)
91
+ end
92
+
93
+ test 'checks build_exists_condition for a false condition' do
94
+ assert_equal Sequel::Database::IF_NOT_EXISTS, MockDB.build_exists_condition(false)
95
+ end
96
+
97
+ test 'checks build_exists_condition for a non boolean condition' do
98
+ assert_nil MockDB.build_exists_condition('')
99
+ end
100
+ end
@@ -91,20 +91,41 @@ class MysqlSequenceTest < Minitest::Test
91
91
  assert_operator (2 + @step), :>, MysqlDB.nextval(:position)
92
92
  end
93
93
 
94
- test "returns current/last sequence value, which doesn't increase by itself" do
94
+ test %( returns current/last sequence value, which doesn't increase by itself
95
+ for migration WITHOUT 'start' or 'increment' values ) do
95
96
  with_migration do
96
97
  def up
97
98
  create_sequence :position
98
99
  end
99
100
  end.up
100
101
 
102
+ # catch the 'start' value 'by default
103
+ assert_equal 1, MysqlDB.currval(:position)
104
+ assert_equal 1, MysqlDB.lastval(:position)
105
+
101
106
  MysqlDB.nextval(:position)
102
- # changed value (=2) after default one (=1)
103
107
 
104
108
  assert_equal 2, MysqlDB.currval(:position)
105
109
  assert_equal 2, MysqlDB.lastval(:position)
110
+ end
111
+
112
+ test %( returns current/last sequence value, which doesn't increase by itself
113
+ for migration WITH 'start' and 'increment' values ) do
114
+ with_migration do
115
+ def up
116
+ create_sequence :position, start: 2, increment: 3
117
+ end
118
+ end.up
119
+
120
+ # catch the 'start' value
106
121
  assert_equal 2, MysqlDB.currval(:position)
107
122
  assert_equal 2, MysqlDB.lastval(:position)
123
+
124
+ MysqlDB.nextval(:position)
125
+
126
+ # Doesn't support 'increment' value
127
+ assert_equal 3, MysqlDB.currval(:position)
128
+ assert_equal 3, MysqlDB.lastval(:position)
108
129
  end
109
130
 
110
131
  test 'sets a new sequence value greater than the current one' do
@@ -125,7 +146,7 @@ class MysqlSequenceTest < Minitest::Test
125
146
  assert_equal 102, MysqlDB.nextval(:position)
126
147
  end
127
148
 
128
- test 'sets a new sequence value less than the current one' do
149
+ test 'sets a new sequence value less than the current one (does not change the value)' do
129
150
  with_migration do
130
151
  def up
131
152
  create_sequence :position, start: 100
@@ -215,6 +236,12 @@ class MysqlSequenceTest < Minitest::Test
215
236
  end
216
237
 
217
238
  test 'orders sequences' do
239
+ with_migration do
240
+ def up
241
+ drop_table :stuffs, if_exists: true
242
+ end
243
+ end.up
244
+
218
245
  list = MysqlDB.check_sequences.map { |s| s[:name] }
219
246
  assert !list.include?('a')
220
247
  assert !list.include?('b')
@@ -222,7 +249,6 @@ class MysqlSequenceTest < Minitest::Test
222
249
 
223
250
  with_migration do
224
251
  def up
225
- drop_table :things, if_exists: true
226
252
  create_sequence :c, { start: 1 }
227
253
  create_sequence :a, { start: 3 }
228
254
  create_sequence :b
@@ -235,18 +261,6 @@ class MysqlSequenceTest < Minitest::Test
235
261
  assert list.include?('c')
236
262
  end
237
263
 
238
- test 'checks custom sequence generated from code' do
239
- assert_equal MysqlDB.custom_sequence?(:c), false
240
-
241
- with_migration do
242
- def up
243
- create_sequence :c
244
- end
245
- end.up
246
-
247
- assert_equal MysqlDB.custom_sequence?(:c), true
248
- end
249
-
250
264
  test 'recreates the same sequence with the same start value' do
251
265
  with_migration do
252
266
  def up
@@ -352,4 +366,32 @@ class MysqlSequenceTest < Minitest::Test
352
366
 
353
367
  assert_equal pos4 - pos2, 2
354
368
  end
369
+
370
+ test 'checks custom sequence generated from code' do
371
+ assert_equal MysqlDB.custom_sequence?(:c), false
372
+
373
+ with_migration do
374
+ def up
375
+ create_sequence :c
376
+ end
377
+ end.up
378
+
379
+ assert_equal MysqlDB.custom_sequence?(:c), true
380
+ end
381
+
382
+ test "catches a Mysql2::Error: «Table mysql_sequence doesn't exist»" do
383
+ assert !sequence_table_exists?('position')
384
+
385
+ MysqlDB.drop_table :mysql_sequence, if_exists: true
386
+
387
+ last_number = MysqlDB.lastval(:position)
388
+ assert_nil last_number
389
+ end
390
+
391
+ test 'creates a Sequence by calling DB.setval(position, 1) if it still does not exist' do
392
+ assert !sequence_table_exists?('position')
393
+
394
+ MysqlDB.setval(:position, 100)
395
+ assert_equal 100, MysqlDB.currval(:position)
396
+ end
355
397
  end
@@ -72,33 +72,80 @@ class PostgresqlSequenceTest < Minitest::Test
72
72
  assert_equal 3, PostgresqlDB.nextval(:position)
73
73
  end
74
74
 
75
- test "returns current/last sequence value, which doesn't increase by itself" do
75
+ test %( returns current/last sequence value, which doesn't increase by itself
76
+ for migration WITHOUT 'start' or 'increment' values ) do
76
77
  with_migration do
77
78
  def up
78
- create_sequence :position, start: 2, increment: 2
79
+ create_sequence :position
79
80
  end
80
81
  end.up
81
82
 
83
+ # catch the 'start' value
84
+ assert_equal 1, PostgresqlDB.currval(:position)
85
+ # is the same value
86
+ assert_equal 1, PostgresqlDB.lastval(:position)
87
+
82
88
  PostgresqlDB.nextval(:position)
83
89
 
84
90
  assert_equal 2, PostgresqlDB.currval(:position)
85
91
  assert_equal 2, PostgresqlDB.lastval(:position)
92
+ end
93
+
94
+ test %( returns current/last sequence value, which doesn't increase by itself
95
+ for migration WITH 'start' and 'increment' values ) do
96
+ with_migration do
97
+ def up
98
+ create_sequence :position, start: 2, increment: 3
99
+ end
100
+ end.up
101
+
102
+ # catch the 'start' value
86
103
  assert_equal 2, PostgresqlDB.currval(:position)
104
+ # is the same value
87
105
  assert_equal 2, PostgresqlDB.lastval(:position)
106
+
107
+ PostgresqlDB.nextval(:position)
108
+
109
+ # support 'increment' value
110
+ assert_equal 5, PostgresqlDB.currval(:position)
111
+ assert_equal 5, PostgresqlDB.lastval(:position)
88
112
  end
89
113
 
90
- test 'sets sequence value' do
114
+ test 'sets a new sequence value greater than the current one' do
91
115
  with_migration do
92
116
  def up
93
117
  create_sequence :position
94
118
  end
95
119
  end.up
96
120
 
97
- PostgresqlDB.nextval(:position)
98
121
  assert_equal PostgresqlDB.currval(:position), 1
99
122
 
123
+ PostgresqlDB.nextval(:position)
124
+ assert_equal PostgresqlDB.currval(:position), 2
125
+
100
126
  PostgresqlDB.setval(:position, 101)
101
- assert_equal 101, PostgresqlDB.currval(:position)
127
+ assert_equal 101, PostgresqlDB.lastval(:position)
128
+
129
+ assert_equal 102, PostgresqlDB.nextval(:position)
130
+ end
131
+
132
+ test 'sets a new sequence value less than the current one (change the value as an EXCEPTION)' do
133
+ with_migration do
134
+ def up
135
+ create_sequence :position, start: 100
136
+ end
137
+ end.up
138
+
139
+ assert_equal PostgresqlDB.currval(:position), 100
140
+
141
+ PostgresqlDB.nextval(:position)
142
+ assert_equal PostgresqlDB.currval(:position), 101
143
+
144
+ PostgresqlDB.setval(:position, 1)
145
+ assert_equal 1, PostgresqlDB.lastval(:position)
146
+
147
+ PostgresqlDB.nextval(:position)
148
+ assert_equal 2, PostgresqlDB.lastval(:position)
102
149
  end
103
150
 
104
151
  test 'drops sequence and check_sequences' do
@@ -128,6 +175,12 @@ class PostgresqlSequenceTest < Minitest::Test
128
175
  end
129
176
 
130
177
  test 'orders sequences' do
178
+ with_migration do
179
+ def up
180
+ drop_table :things, if_exists: true
181
+ end
182
+ end.up
183
+
131
184
  list = PostgresqlDB.check_sequences.map { |s| s[:sequence_name] }
132
185
  assert !list.include?('a')
133
186
  assert !list.include?('b')
@@ -135,7 +188,6 @@ class PostgresqlSequenceTest < Minitest::Test
135
188
 
136
189
  with_migration do
137
190
  def up
138
- drop_table :things, if_exists: true
139
191
  create_sequence :c
140
192
  create_sequence :a
141
193
  create_sequence :b
@@ -76,20 +76,41 @@ class SqliteSequenceTest < Minitest::Test
76
76
  assert_operator (2 + @step), :>, SQLiteDB.nextval(:position)
77
77
  end
78
78
 
79
- test "returns current/last sequence value, which doesn't increase by itself" do
79
+ test %( returns current/last sequence value, which doesn't increase by itself
80
+ for migration WITHOUT 'start' or 'increment' values ) do
80
81
  with_migration do
81
82
  def up
82
83
  create_sequence :position
83
84
  end
84
85
  end.up
85
86
 
87
+ # catch the 'start' value 'by default
88
+ assert_equal 1, SQLiteDB.currval(:position)
89
+ assert_equal 1, SQLiteDB.lastval(:position)
90
+
86
91
  SQLiteDB.nextval(:position)
87
- # changed value (=2) after default one (=1)
88
92
 
89
93
  assert_equal 2, SQLiteDB.currval(:position)
90
94
  assert_equal 2, SQLiteDB.lastval(:position)
95
+ end
96
+
97
+ test %( returns current/last sequence value, which doesn't increase by itself
98
+ for migration WITH 'start' and 'increment' values ) do
99
+ with_migration do
100
+ def up
101
+ create_sequence :position, start: 2, increment: 3
102
+ end
103
+ end.up
104
+
105
+ # catch the 'start' value
91
106
  assert_equal 2, SQLiteDB.currval(:position)
92
107
  assert_equal 2, SQLiteDB.lastval(:position)
108
+
109
+ SQLiteDB.nextval(:position)
110
+
111
+ # Doesn't support 'increment' value
112
+ assert_equal 3, SQLiteDB.currval(:position)
113
+ assert_equal 3, SQLiteDB.lastval(:position)
93
114
  end
94
115
 
95
116
  test 'sets a new sequence value greater than the current one' do
@@ -111,7 +132,7 @@ class SqliteSequenceTest < Minitest::Test
111
132
  assert_equal 102, SQLiteDB.lastval(:position)
112
133
  end
113
134
 
114
- test 'sets a new sequence value less than the current one' do
135
+ test 'sets a new sequence value less than the current one (does not change the value)' do
115
136
  with_migration do
116
137
  def up
117
138
  create_sequence :position, start: 100
@@ -166,9 +187,7 @@ class SqliteSequenceTest < Minitest::Test
166
187
  end
167
188
  end.down
168
189
 
169
- sequence = SQLiteDB.check_sequences.find do |seq|
170
- seq[:name] == 'position'
171
- end
190
+ sequence = (list = SQLiteDB.check_sequences).empty? ? nil : list
172
191
 
173
192
  assert_nil sequence
174
193
  end
@@ -192,14 +211,18 @@ class SqliteSequenceTest < Minitest::Test
192
211
  end
193
212
  end.down
194
213
 
195
- sequence = SQLiteDB.check_sequences.find do |seq|
196
- seq[:name] == 'position'
197
- end
214
+ sequence = (list = SQLiteDB.check_sequences).empty? ? nil : list
198
215
 
199
216
  assert_nil sequence
200
217
  end
201
218
 
202
219
  test 'orders sequences' do
220
+ with_migration do
221
+ def up
222
+ drop_table :objects, if_exists: true
223
+ end
224
+ end.up
225
+
203
226
  list = SQLiteDB.check_sequences.map { |s| s[:name] }
204
227
  assert !list.include?('a')
205
228
  assert !list.include?('b')
@@ -207,7 +230,6 @@ class SqliteSequenceTest < Minitest::Test
207
230
 
208
231
  with_migration do
209
232
  def up
210
- drop_table :things, if_exists: true
211
233
  create_sequence :c, { start: 1 }
212
234
  create_sequence :a, { start: 3 }
213
235
  create_sequence :b
@@ -295,7 +317,6 @@ class SqliteSequenceTest < Minitest::Test
295
317
  test 'creates table that references sequence' do
296
318
  with_migration do
297
319
  def up
298
- drop_table :apprentices, if_exists: true
299
320
  create_sequence :position_id, if_exists: false, start: 1
300
321
  create_table :apprentices do
301
322
  primary_key :id
@@ -326,4 +347,23 @@ class SqliteSequenceTest < Minitest::Test
326
347
 
327
348
  assert_equal pos4 - pos2, 2
328
349
  end
350
+
351
+ test 'checks custom sequence generated from code' do
352
+ assert_equal SQLiteDB.custom_sequence?(:c), false
353
+
354
+ with_migration do
355
+ def up
356
+ create_sequence :c
357
+ end
358
+ end.up
359
+
360
+ assert_equal SQLiteDB.custom_sequence?(:c), true
361
+ end
362
+
363
+ test 'creates a Sequence by calling DB.setval(position, 1) if it still does not exist' do
364
+ assert !sequence_table_exists?('position')
365
+
366
+ SQLiteDB.setval(:position, 100)
367
+ assert_equal 100, SQLiteDB.currval(:position)
368
+ end
329
369
  end
@@ -10,9 +10,10 @@ SQLiteDB = Sequel.connect(
10
10
 
11
11
  module SqliteTestHelper
12
12
  def recreate_table
13
+ SQLiteDB.drop_table :apprentices, if_exists: true
13
14
  SQLiteDB.drop_sequence :position
14
15
  SQLiteDB.drop_sequence :position_id, if_exists: true
15
- SQLiteDB.run 'DROP TABLE IF EXISTS objects'
16
+ SQLiteDB.drop_table :objects, if_exists: true
16
17
  SQLiteDB.drop_sequence 'a'
17
18
  SQLiteDB.drop_sequence 'b'
18
19
  SQLiteDB.drop_sequence 'c'
@@ -27,4 +28,10 @@ module SqliteTestHelper
27
28
 
28
29
  Class.new(migration_class, &block).new(SQLiteDB)
29
30
  end
31
+
32
+ def sequence_table_exists?(name)
33
+ sql = "SELECT name FROM sqlite_schema WHERE type ='table' AND name NOT LIKE 'sqlite_%';"
34
+ table_list = SQLiteDB.fetch(sql).all.map { |_key, value| value }
35
+ table_list.include?(name)
36
+ end
30
37
  end
data/test/test_helper.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'simplecov'
4
+
4
5
  SimpleCov.start
5
6
 
6
7
  require 'bundler/setup'