@@ -15,7 +15,7 @@ pub fn ping(data: &Data, issue: &Issue) -> Result<()> {
15
15
}
16
16
17
17
pub fn run ( host : & str , data : & Data , issue : & Issue , args : RunArgs ) -> Result < ( ) > {
18
- let name = get_name ( & data. db , issue, args. name ) ?;
18
+ let name = setup_run_name ( & data. db , issue, args. name ) ?;
19
19
20
20
:: actions:: CreateExperiment {
21
21
name : name. clone ( ) ,
@@ -167,12 +167,57 @@ fn default_experiment_name(db: &Database, issue: &Issue) -> Result<Option<String
167
167
} )
168
168
}
169
169
170
+ /// Set up the name for a new run's experiment, including auto-incrementing generated names and
171
+ /// storing experiment names in the database.
172
+ fn setup_run_name ( db : & Database , issue : & Issue , name : Option < String > ) -> Result < String > {
173
+ let name = if let Some ( name) = name {
174
+ name
175
+ } else {
176
+ generate_new_experiment_name ( & db, & issue) ?
177
+ } ;
178
+ store_experiment_name ( & db, issue, & name) ?;
179
+ Ok ( name)
180
+ }
181
+
182
+ /// Automatically generate experiment name, auto-incrementing to the first one which does not
183
+ /// exist. E.g. if this function is passed the an issue `12345`, and experiment `pr-12345`
184
+ /// exists, then this command returns Ok("pr-12345-1"). Does not store the result in the database.
185
+ fn generate_new_experiment_name ( db : & Database , issue : & Issue ) -> Result < String > {
186
+ let mut name = format ! ( "pr-{}" , issue. number) ;
187
+ let mut idx = 1u16 ;
188
+ while Experiment :: exists ( & db, & name) ? {
189
+ name = format ! ( "pr-{}-{}" , issue. number, idx) ;
190
+ idx = idx
191
+ . checked_add ( 1 )
192
+ . ok_or_else :: < Error , _ > ( || "too many similarly-named pull requests" . into ( ) ) ?;
193
+ }
194
+ Ok ( name)
195
+ }
196
+
170
197
#[ cfg( test) ]
171
198
mod tests {
172
- use super :: { default_experiment_name, store_experiment_name} ;
199
+ use super :: {
200
+ default_experiment_name, generate_new_experiment_name, get_name, setup_run_name,
201
+ store_experiment_name,
202
+ } ;
173
203
use db:: Database ;
204
+ use errors:: * ;
174
205
use server:: github;
175
206
207
+ /// Simulate to the `run` command, and return experiment name
208
+ fn dummy_run ( db : & Database , issue : & github:: Issue , name : Option < String > ) -> Result < String > {
209
+ let name = setup_run_name ( db, issue, name) ?;
210
+ :: actions:: CreateExperiment :: dummy ( & name) . apply ( & db, & :: config:: Config :: default ( ) ) ?;
211
+ Ok ( name)
212
+ }
213
+
214
+ /// Simulate to the `edit` command, and return experiment name
215
+ fn dummy_edit ( db : & Database , issue : & github:: Issue , name : Option < String > ) -> Result < String > {
216
+ let name = get_name ( db, issue, name) ?;
217
+ :: actions:: EditExperiment :: dummy ( & name) . apply ( & db, & :: config:: Config :: default ( ) ) ?;
218
+ Ok ( name)
219
+ }
220
+
176
221
#[ test]
177
222
fn test_default_experiment_name ( ) {
178
223
let db = Database :: temp ( ) . unwrap ( ) ;
@@ -209,4 +254,145 @@ mod tests {
209
254
"foo"
210
255
) ;
211
256
}
257
+
258
+ #[ test]
259
+ fn test_run ( ) {
260
+ let db = Database :: temp ( ) . unwrap ( ) ;
261
+
262
+ let pr1 = github:: Issue {
263
+ number : 1 ,
264
+ url : String :: new ( ) ,
265
+ html_url : String :: new ( ) ,
266
+ labels : Vec :: new ( ) ,
267
+ pull_request : Some ( github:: PullRequest {
268
+ html_url : String :: new ( ) ,
269
+ } ) ,
270
+ } ;
271
+ // test with supplied name
272
+ assert_eq ! (
273
+ dummy_run( & db, & pr1, Some ( "pr-1" . to_owned( ) ) ) . expect( "dummy run failed" ) ,
274
+ "pr-1"
275
+ ) ;
276
+ // make sure it fails the second time
277
+ assert ! ( dummy_run( & db, & pr1, Some ( "pr-1" . to_owned( ) ) ) . is_err( ) , ) ;
278
+
279
+ let pr2 = github:: Issue {
280
+ number : 2 ,
281
+ url : String :: new ( ) ,
282
+ html_url : String :: new ( ) ,
283
+ labels : Vec :: new ( ) ,
284
+ pull_request : Some ( github:: PullRequest {
285
+ html_url : String :: new ( ) ,
286
+ } ) ,
287
+ } ;
288
+ // test with default-generated name
289
+ assert_eq ! (
290
+ dummy_run( & db, & pr2, None ) . expect( "dummy run failed" ) ,
291
+ "pr-2"
292
+ ) ;
293
+ // make sure it increments correctly
294
+ assert_eq ! (
295
+ dummy_run( & db, & pr2, None ) . expect( "dummy run failed" ) ,
296
+ "pr-2-1"
297
+ ) ;
298
+ // make sure we don't get e.g. pr-2-1-1
299
+ assert_eq ! (
300
+ dummy_run( & db, & pr2, None ) . expect( "dummy run failed" ) ,
301
+ "pr-2-2"
302
+ ) ;
303
+ // make sure we can manually supply name and then continue incrementing
304
+ assert_eq ! (
305
+ dummy_run( & db, & pr1, Some ( "pr-2-custom" . to_owned( ) ) ) . expect( "dummy run failed" ) ,
306
+ "pr-2-custom"
307
+ ) ;
308
+ assert_eq ! (
309
+ dummy_run( & db, & pr2, None ) . expect( "dummy run failed" ) ,
310
+ "pr-2-3"
311
+ ) ;
312
+ }
313
+
314
+ #[ test]
315
+ fn test_edit ( ) {
316
+ let db = Database :: temp ( ) . unwrap ( ) ;
317
+
318
+ // test retrieval of name generated in a supplied-name run
319
+ let pr1 = github:: Issue {
320
+ number : 1 ,
321
+ url : String :: new ( ) ,
322
+ html_url : String :: new ( ) ,
323
+ labels : Vec :: new ( ) ,
324
+ pull_request : Some ( github:: PullRequest {
325
+ html_url : String :: new ( ) ,
326
+ } ) ,
327
+ } ;
328
+ assert_eq ! (
329
+ dummy_run( & db, & pr1, Some ( "pr-1-custom" . to_owned( ) ) ) . expect( "dummy run failed" ) ,
330
+ "pr-1-custom"
331
+ ) ;
332
+ assert_eq ! (
333
+ dummy_edit( & db, & pr1, None ) . expect( "dummy edit failed" ) ,
334
+ "pr-1-custom"
335
+ ) ;
336
+
337
+ // test retrieval of name generated in an auto-generated run
338
+ let pr2 = github:: Issue {
339
+ number : 2 ,
340
+ url : String :: new ( ) ,
341
+ html_url : String :: new ( ) ,
342
+ labels : Vec :: new ( ) ,
343
+ pull_request : Some ( github:: PullRequest {
344
+ html_url : String :: new ( ) ,
345
+ } ) ,
346
+ } ;
347
+ assert_eq ! (
348
+ dummy_run( & db, & pr2, None ) . expect( "dummy run failed" ) ,
349
+ "pr-2"
350
+ ) ;
351
+ // make sure edit doesn't change name
352
+ assert_eq ! (
353
+ dummy_edit( & db, & pr2, None ) . expect( "dummy edit failed" ) ,
354
+ "pr-2"
355
+ ) ;
356
+ // test idempotence
357
+ assert_eq ! (
358
+ dummy_edit( & db, & pr2, None ) . expect( "dummy edit failed" ) ,
359
+ "pr-2"
360
+ ) ;
361
+ // test that name incrementing is reflected here
362
+ assert_eq ! (
363
+ dummy_run( & db, & pr2, None ) . expect( "dummy run failed" ) ,
364
+ "pr-2-1"
365
+ ) ;
366
+ assert_eq ! (
367
+ dummy_edit( & db, & pr2, None ) . expect( "dummy edit failed" ) ,
368
+ "pr-2-1"
369
+ ) ;
370
+ }
371
+
372
+ #[ test]
373
+ fn test_generate_new_experiment_name ( ) {
374
+ let db = Database :: temp ( ) . unwrap ( ) ;
375
+ let pr = github:: Issue {
376
+ number : 12345 ,
377
+ url : String :: new ( ) ,
378
+ html_url : String :: new ( ) ,
379
+ labels : Vec :: new ( ) ,
380
+ pull_request : Some ( github:: PullRequest {
381
+ html_url : String :: new ( ) ,
382
+ } ) ,
383
+ } ;
384
+
385
+ :: actions:: CreateExperiment :: dummy ( "pr-12345" )
386
+ . apply ( & db, & :: config:: Config :: default ( ) )
387
+ . expect ( "could not store dummy experiment" ) ;
388
+ let new_name = generate_new_experiment_name ( & db, & pr) . unwrap ( ) ;
389
+ assert_eq ! ( new_name, "pr-12345-1" ) ;
390
+ :: actions:: CreateExperiment :: dummy ( "pr-12345-1" )
391
+ . apply ( & db, & :: config:: Config :: default ( ) )
392
+ . expect ( "could not store dummy experiment" ) ; ;
393
+ assert_eq ! (
394
+ & generate_new_experiment_name( & db, & pr) . unwrap( ) ,
395
+ "pr-12345-2"
396
+ ) ;
397
+ }
212
398
}
0 commit comments