cassowary_test.dart 17.1 KB
Newer Older
1
// Copyright 2016 The Chromium Authors. All rights reserved.
Chinmay Garde's avatar
Chinmay Garde committed
2 3 4 5 6
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:test/test.dart';

7
import 'package:flutter/cassowary.dart';
Chinmay Garde's avatar
Chinmay Garde committed
8 9 10

void main() {
  test('variable', () {
11
    Param v = new Param(22.0);
Chinmay Garde's avatar
Chinmay Garde committed
12 13 14 15
    expect(v.value, 22);
  });

  test('variable1', () {
16
    Param v = new Param(22.0);
17 18
    expect((v + cm(22.0)).value, 44.0);
    expect((v - cm(20.0)).value, 2.0);
Chinmay Garde's avatar
Chinmay Garde committed
19 20 21
  });

  test('term', () {
22
    Term t = new Term(new Variable(22.0), 2.0);
Chinmay Garde's avatar
Chinmay Garde committed
23 24 25 26
    expect(t.value, 44);
  });

  test('expression', () {
27
    List<Term> terms = <Term>[
Chinmay Garde's avatar
Chinmay Garde committed
28 29 30
      new Term(new Variable(22.0), 2.0),
      new Term(new Variable(1.0), 1.0),
    ];
31
    Expression e = new Expression(terms, 40.0);
Chinmay Garde's avatar
Chinmay Garde committed
32 33 34 35
    expect(e.value, 85.0);
  });

  test('expression1', () {
36 37 38
    Param v1 = new Param(10.0);
    Param v2 = new Param(10.0);
    Param v3 = new Param(22.0);
Chinmay Garde's avatar
Chinmay Garde committed
39

40
    expect(v1 is Param, true);
41
    expect(v1 + cm(20.0) is Expression, true);
Chinmay Garde's avatar
Chinmay Garde committed
42 43 44 45 46 47 48 49 50 51
    expect(v1 + v2 is Expression, true);

    expect((v1 + v2).value, 20.0);
    expect((v1 - v2).value, 0.0);

    expect((v1 + v2 + v3) is Expression, true);
    expect((v1 + v2 + v3).value, 42.0);
  });

  test('expression2', () {
52
    Expression e = new Param(10.0) + cm(5.0);
Chinmay Garde's avatar
Chinmay Garde committed
53 54 55 56
    expect(e.value, 15.0);
    expect(e is Expression, true);

    // Constant
57 58 59 60
    expect((e + cm(2.0)) is Expression, true);
    expect((e + cm(2.0)).value, 17.0);
    expect((e - cm(2.0)) is Expression, true);
    expect((e - cm(2.0)).value, 13.0);
Chinmay Garde's avatar
Chinmay Garde committed
61 62 63

    expect(e.value, 15.0);

64
    // Param
65
    Param v = new Param(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
66 67 68 69 70 71 72 73
    expect((e + v) is Expression, true);
    expect((e + v).value, 17.0);
    expect((e - v) is Expression, true);
    expect((e - v).value, 13.0);

    expect(e.value, 15.0);

    // Term
74
    Term t = new Term(v.variable, 2.0);
Chinmay Garde's avatar
Chinmay Garde committed
75 76 77 78 79 80 81 82
    expect((e + t) is Expression, true);
    expect((e + t).value, 19.0);
    expect((e - t) is Expression, true);
    expect((e - t).value, 11.0);

    expect(e.value, 15.0);

    // Expression
83
    Expression e2 = new Param(7.0) + new Param(3.0);
Chinmay Garde's avatar
Chinmay Garde committed
84 85 86 87 88 89 90 91 92
    expect((e + e2) is Expression, true);
    expect((e + e2).value, 25.0);
    expect((e - e2) is Expression, true);
    expect((e - e2).value, 5.0);

    expect(e.value, 15.0);
  });

  test('term2', () {
93
    Term t = new Term(new Variable(12.0), 1.0);
Chinmay Garde's avatar
Chinmay Garde committed
94 95

    // Constant
96
    ConstantMember c = cm(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
97 98 99 100 101 102
    expect((t + c) is Expression, true);
    expect((t + c).value, 14.0);
    expect((t - c) is Expression, true);
    expect((t - c).value, 10.0);

    // Variable
103
    Param v = new Param(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
104 105 106 107 108 109
    expect((t + v) is Expression, true);
    expect((t + v).value, 14.0);
    expect((t - v) is Expression, true);
    expect((t - v).value, 10.0);

    // Term
110
    Term t2 = new Term(new Variable(1.0), 2.0);
Chinmay Garde's avatar
Chinmay Garde committed
111 112 113 114 115 116
    expect((t + t2) is Expression, true);
    expect((t + t2).value, 14.0);
    expect((t - t2) is Expression, true);
    expect((t - t2).value, 10.0);

    // Expression
117
    Expression exp = new Param(1.0) + cm(1.0);
Chinmay Garde's avatar
Chinmay Garde committed
118 119 120 121 122 123 124
    expect((t + exp) is Expression, true);
    expect((t + exp).value, 14.0);
    expect((t - exp) is Expression, true);
    expect((t - exp).value, 10.0);
  });

  test('variable3', () {
125
    Param v = new Param(3.0);
Chinmay Garde's avatar
Chinmay Garde committed
126 127

    // Constant
128
    ConstantMember c = cm(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
129 130 131 132 133 134
    expect((v + c) is Expression, true);
    expect((v + c).value, 5.0);
    expect((v - c) is Expression, true);
    expect((v - c).value, 1.0);

    // Variable
135
    Param v2 = new Param(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
136 137 138 139 140 141
    expect((v + v2) is Expression, true);
    expect((v + v2).value, 5.0);
    expect((v - v2) is Expression, true);
    expect((v - v2).value, 1.0);

    // Term
142
    Term t2 = new Term(new Variable(1.0), 2.0);
Chinmay Garde's avatar
Chinmay Garde committed
143 144 145 146 147 148
    expect((v + t2) is Expression, true);
    expect((v + t2).value, 5.0);
    expect((v - t2) is Expression, true);
    expect((v - t2).value, 1.0);

    // Expression
149
    Expression exp = new Param(1.0) + cm(1.0);
Chinmay Garde's avatar
Chinmay Garde committed
150 151 152 153 154 155 156 157 158
    expect(exp.terms.length, 1);

    expect((v + exp) is Expression, true);
    expect((v + exp).value, 5.0);
    expect((v - exp) is Expression, true);
    expect((v - exp).value, 1.0);
  });

  test('constantmember', () {
159
    ConstantMember c = cm(3.0);
Chinmay Garde's avatar
Chinmay Garde committed
160 161

    // Constant
162
    ConstantMember c2 = cm(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
163 164 165 166 167 168
    expect((c + c2) is Expression, true);
    expect((c + c2).value, 5.0);
    expect((c - c2) is Expression, true);
    expect((c - c2).value, 1.0);

    // Variable
169
    Param v2 = new Param(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
170 171 172 173 174 175
    expect((c + v2) is Expression, true);
    expect((c + v2).value, 5.0);
    expect((c - v2) is Expression, true);
    expect((c - v2).value, 1.0);

    // Term
176
    Term t2 = new Term(new Variable(1.0), 2.0);
Chinmay Garde's avatar
Chinmay Garde committed
177 178 179 180 181 182
    expect((c + t2) is Expression, true);
    expect((c + t2).value, 5.0);
    expect((c - t2) is Expression, true);
    expect((c - t2).value, 1.0);

    // Expression
183
    Expression exp = new Param(1.0) + cm(1.0);
Chinmay Garde's avatar
Chinmay Garde committed
184 185 186 187 188 189 190 191

    expect((c + exp) is Expression, true);
    expect((c + exp).value, 5.0);
    expect((c - exp) is Expression, true);
    expect((c - exp).value, 1.0);
  });

  test('constraint2', () {
192 193
    Param left = new Param(10.0);
    Param right = new Param(100.0);
Chinmay Garde's avatar
Chinmay Garde committed
194

195
    Constraint c = right - left >= cm(25.0);
Chinmay Garde's avatar
Chinmay Garde committed
196 197 198 199 200
    expect(c is Constraint, true);
  });

  test('simple_multiplication', () {
    // Constant
201
    ConstantMember c = cm(20.0);
202
    expect((c * cm(2.0)).value, 40.0);
Chinmay Garde's avatar
Chinmay Garde committed
203 204

    // Variable
205
    Param v = new Param(20.0);
206
    expect((v * cm(2.0)).value, 40.0);
Chinmay Garde's avatar
Chinmay Garde committed
207 208

    // Term
209
    Term t = new Term(v.variable, 1.0);
210
    expect((t * cm(2.0)).value, 40.0);
Chinmay Garde's avatar
Chinmay Garde committed
211 212

    // Expression
213
    Expression e = new Expression(<Term>[t], 0.0);
214
    expect((e * cm(2.0)).value, 40.0);
Chinmay Garde's avatar
Chinmay Garde committed
215 216 217 218
  });

  test('simple_division', () {
    // Constant
219
    ConstantMember c = cm(20.0);
220
    expect((c / cm(2.0)).value, 10.0);
Chinmay Garde's avatar
Chinmay Garde committed
221 222

    // Variable
223
    Param v = new Param(20.0);
224
    expect((v / cm(2.0)).value, 10.0);
Chinmay Garde's avatar
Chinmay Garde committed
225 226

    // Term
227
    Term t = new Term(v.variable, 1.0);
228
    expect((t / cm(2.0)).value, 10.0);
Chinmay Garde's avatar
Chinmay Garde committed
229 230

    // Expression
231
    Expression e = new Expression(<Term>[t], 0.0);
232
    expect((e / cm(2.0)).value, 10.0);
Chinmay Garde's avatar
Chinmay Garde committed
233 234 235
  });

  test('full_constraints_setup', () {
236 237
    Param left = new Param(2.0);
    Param right = new Param(10.0);
Chinmay Garde's avatar
Chinmay Garde committed
238

239
    Constraint c1 = right - left >= cm(20.0);
Chinmay Garde's avatar
Chinmay Garde committed
240 241 242 243
    expect(c1 is Constraint, true);
    expect(c1.expression.constant, -20.0);
    expect(c1.relation, Relation.greaterThanOrEqualTo);

244
    Constraint c2 = (right - left).equals(cm(30.0));
Chinmay Garde's avatar
Chinmay Garde committed
245 246 247 248
    expect(c2 is Constraint, true);
    expect(c2.expression.constant, -30.0);
    expect(c2.relation, Relation.equalTo);

249
    Constraint c3 = right - left <= cm(30.0);
Chinmay Garde's avatar
Chinmay Garde committed
250 251 252 253
    expect(c3 is Constraint, true);
    expect(c3.expression.constant, -30.0);
    expect(c3.relation, Relation.lessThanOrEqualTo);
  });
254 255

  test('constraint_strength_update', () {
256 257
    Param left = new Param(2.0);
    Param right = new Param(10.0);
258

259
    Constraint c = (right - left >= cm(200.0)) | 750.0;
260 261 262 263 264
    expect(c is Constraint, true);
    expect(c.expression.terms.length, 2);
    expect(c.expression.constant, -200.0);
    expect(c.priority, 750.0);
  });
265 266

  test('solver', () {
267
    Solver s = new Solver();
268

269 270
    Param left = new Param(2.0);
    Param right = new Param(100.0);
271

272
    Constraint c1 = right - left >= cm(200.0);
273

274 275
    expect((right >= left) is Constraint, true);

276
    expect(s.addConstraint(c1), Result.success);
277 278 279
  });

  test('constraint_complex', () {
280
    Expression e = new Param(200.0) - new Param(100.0);
281 282

    // Constant
283
    Constraint c1 = e >= cm(50.0);
284 285 286 287 288
    expect(c1 is Constraint, true);
    expect(c1.expression.terms.length, 2);
    expect(c1.expression.constant, -50.0);

    // Variable
289
    Constraint c2 = e >= new Param(2.0);
290 291 292 293 294
    expect(c2 is Constraint, true);
    expect(c2.expression.terms.length, 3);
    expect(c2.expression.constant, 0.0);

    // Term
295
    Constraint c3 = e >= new Term(new Variable(2.0), 1.0);
296 297 298 299 300
    expect(c3 is Constraint, true);
    expect(c3.expression.terms.length, 3);
    expect(c3.expression.constant, 0.0);

    // Expression
301
    Constraint c4 = e >= new Expression(<Term>[new Term(new Variable(2.0), 1.0)], 20.0);
302 303 304 305 306 307 308
    expect(c4 is Constraint, true);
    expect(c4.expression.terms.length, 3);
    expect(c4.expression.constant, -20.0);
  });

  test('constraint_complex_non_exprs', () {
    // Constant
309
    Constraint c1 = cm(100.0) >= cm(50.0);
310 311 312 313 314
    expect(c1 is Constraint, true);
    expect(c1.expression.terms.length, 0);
    expect(c1.expression.constant, 50.0);

    // Variable
315
    Constraint c2 = new Param(100.0) >= new Param(2.0);
316 317 318 319 320
    expect(c2 is Constraint, true);
    expect(c2.expression.terms.length, 2);
    expect(c2.expression.constant, 0.0);

    // Term
321 322
    Term t = new Term(new Variable(100.0), 1.0);
    Constraint c3 = t >= new Term(new Variable(2.0), 1.0);
323 324 325 326 327
    expect(c3 is Constraint, true);
    expect(c3.expression.terms.length, 2);
    expect(c3.expression.constant, 0.0);

    // Expression
328 329
    Expression e = new Expression(<Term>[t], 0.0);
    Constraint c4 = e >= new Expression(<Term>[new Term(new Variable(2.0), 1.0)], 20.0);
330 331 332 333
    expect(c4 is Constraint, true);
    expect(c4.expression.terms.length, 2);
    expect(c4.expression.constant, -20.0);
  });
334 335

  test('constraint_update_in_solver', () {
336
    Solver s = new Solver();
337

338 339
    Param left = new Param(2.0);
    Param right = new Param(100.0);
340

341 342
    Constraint c1 = right - left >= cm(200.0);
    Constraint c2 = right >= right;
343 344 345 346 347 348 349

    expect(s.addConstraint(c1), Result.success);
    expect(s.addConstraint(c1), Result.duplicateConstraint);
    expect(s.removeConstraint(c2), Result.unknownConstraint);
    expect(s.removeConstraint(c1), Result.success);
    expect(s.removeConstraint(c1), Result.unknownConstraint);
  });
350 351

  test('test_multiplication_division_override', () {
352 353 354
    ConstantMember c = cm(10.0);
    Param v = new Param(c.value);
    Term t = new Term(v.variable, 1.0);
355
    Expression e = new Expression(<Term>[t], 0.0);
356 357

    // Constant
358
    expect((c * cm(10.0)).value, 100);
359 360

    // Variable
361
    expect((v * cm(10.0)).value, 100);
362 363

    // Term
364
    expect((t * cm(10.0)).value, 100);
365 366

    // Expression
367
    expect((e * cm(10.0)).value, 100);
368 369

    // Constant
370
    expect((c / cm(10.0)).value, 1);
371 372

    // Variable
373
    expect((v / cm(10.0)).value, 1);
374 375

    // Term
376
    expect((t / cm(10.0)).value, 1);
377 378

    // Expression
379
    expect((e / cm(10.0)).value, 1);
380 381 382
  });

  test('test_multiplication_division_exceptions', () {
383 384 385
    ConstantMember c = cm(10.0);
    Param v = new Param(c.value);
    Term t = new Term(v.variable, 1.0);
386
    Expression e = new Expression(<Term>[t], 0.0);
387 388 389 390 391 392 393 394 395 396 397 398

    expect((c * c).value, 100);
    expect(() => v * v, throwsA(new isInstanceOf<ParserException>()));
    expect(() => v / v, throwsA(new isInstanceOf<ParserException>()));
    expect(() => v * t, throwsA(new isInstanceOf<ParserException>()));
    expect(() => v / t, throwsA(new isInstanceOf<ParserException>()));
    expect(() => v * e, throwsA(new isInstanceOf<ParserException>()));
    expect(() => v / e, throwsA(new isInstanceOf<ParserException>()));
    expect(() => v * c, returnsNormally);
    expect(() => v / c, returnsNormally);
  });

399 400 401
  test('edit_updates', () {
    Solver s = new Solver();

402 403 404
    Param left = new Param(0.0);
    Param right = new Param(100.0);
    Param mid = new Param(0.0);
405

406
    Constraint c = left + right >= cm(2.0) * mid;
407 408 409 410 411 412 413 414 415 416
    expect(s.addConstraint(c), Result.success);

    expect(s.addEditVariable(mid.variable, 999.0), Result.success);
    expect(
        s.addEditVariable(mid.variable, 999.0), Result.duplicateEditVariable);
    expect(s.removeEditVariable(mid.variable), Result.success);
    expect(s.removeEditVariable(mid.variable), Result.unknownEditVariable);
  });

  test('bug1', () {
417 418 419
    Param left = new Param(0.0);
    Param right = new Param(100.0);
    Param mid = new Param(0.0);
420

421
    expect(((left + right) >= (cm(2.0) * mid)) is Constraint, true);
422
  });
Chinmay Garde's avatar
Chinmay Garde committed
423 424

  test('single_item', () {
425
    Param left = new Param(-20.0);
Chinmay Garde's avatar
Chinmay Garde committed
426
    Solver s = new Solver();
427
    s.addConstraint(left >= cm(0.0));
428
    s.flushUpdates();
Chinmay Garde's avatar
Chinmay Garde committed
429 430 431 432
    expect(left.value, 0.0);
  });

  test('midpoints', () {
433 434 435
    Param left = new Param(0.0)..name = "left";
    Param right = new Param(0.0)..name = "right";
    Param mid = new Param(0.0)..name = "mid";
Chinmay Garde's avatar
Chinmay Garde committed
436 437 438

    Solver s = new Solver();

439
    expect(s.addConstraint((right + left).equals(mid * cm(2.0))),
440
        Result.success);
441 442
    expect(s.addConstraint(right - left >= cm(100.0)), Result.success);
    expect(s.addConstraint(left >= cm(0.0)), Result.success);
Chinmay Garde's avatar
Chinmay Garde committed
443

444
    s.flushUpdates();
Chinmay Garde's avatar
Chinmay Garde committed
445 446 447 448 449

    expect(left.value, 0.0);
    expect(mid.value, 50.0);
    expect(right.value, 100.0);
  });
450 451

  test('addition_of_multiple', () {
452 453 454
    Param left = new Param(0.0);
    Param right = new Param(0.0);
    Param mid = new Param(0.0);
455 456 457

    Solver s = new Solver();

458
    Constraint c = (left >= cm(0.0));
459

460
    expect(s.addConstraints(<Constraint>[
461
      (left + right).equals(cm(2.0) * mid),
462
      (right - left >= cm(100.0)),
463 464 465
      c
    ]), Result.success);

466
    expect(s.addConstraints(<Constraint>[(right >= cm(-20.0)), c]),
467 468
        Result.duplicateConstraint);
  });
469 470

  test('edit_constraints', () {
471 472 473
    Param left = new Param(0.0)..name = "left";
    Param right = new Param(0.0)..name = "right";
    Param mid = new Param(0.0)..name = "mid";
474 475 476

    Solver s = new Solver();

477
    expect(s.addConstraint((right + left).equals(mid * cm(2.0))),
478
        Result.success);
479 480
    expect(s.addConstraint(right - left >= cm(100.0)), Result.success);
    expect(s.addConstraint(left >= cm(0.0)), Result.success);
481 482 483 484

    expect(s.addEditVariable(mid.variable, Priority.strong), Result.success);
    expect(s.suggestValueForVariable(mid.variable, 300.0), Result.success);

485
    s.flushUpdates();
486 487 488 489 490

    expect(left.value, 0.0);
    expect(mid.value, 300.0);
    expect(right.value, 600.0);
  });
491 492

  test('test_description', () {
493 494 495 496 497
    Param left = new Param(0.0);
    Param right = new Param(100.0);
    Constraint c1 = right >= left;
    Constraint c2 = right <= left;
    Constraint c3 = right.equals(left);
498 499

    Solver s = new Solver();
500 501 502
    expect(s.addConstraint(c1), Result.success);
    expect(s.addConstraint(c2), Result.success);
    expect(s.addConstraint(c3), Result.success);
503 504 505

    expect(s.toString() != null, true);
  });
506 507 508 509 510 511 512 513 514 515 516 517 518

  test('solution_with_optimize', () {
    Param p1 = new Param();
    Param p2 = new Param();
    Param p3 = new Param();

    Param container = new Param();

    Solver solver = new Solver();

    solver.addEditVariable(container.variable, Priority.strong);
    solver.suggestValueForVariable(container.variable, 100.0);

519
    solver.addConstraint((p1 >= cm(30.0)) | Priority.strong);
520 521 522
    solver.addConstraint(p1.equals(p3) | Priority.medium);
    solver.addConstraint(p2.equals(cm(2.0) * p1));
    solver.addConstraint(container.equals(p1 + p2 + p3));
523

524
    solver.flushUpdates();
525 526 527 528 529 530 531

    expect(container.value, 100.0);

    expect(p1.value, 30.0);
    expect(p2.value, 60.0);
    expect(p3.value, 10.0);
  });
532 533

  test('test_updates_collection', () {
534 535 536
    Param left = new Param.withContext("left");
    Param mid = new Param.withContext("mid");
    Param right = new Param.withContext("right");
537 538 539 540 541

    Solver s = new Solver();

    expect(s.addEditVariable(mid.variable, Priority.strong), Result.success);

542
    expect(s.addConstraint((mid * cm(2.0)).equals(left + right)),
543
        Result.success);
544
    expect(s.addConstraint(left >= cm(0.0)), Result.success);
545 546 547

    expect(s.suggestValueForVariable(mid.variable, 50.0), Result.success);

548
    Set<dynamic> updates = s.flushUpdates();
549 550 551 552 553 554 555

    expect(updates.length, 2);

    expect(left.value, 0.0);
    expect(mid.value, 50.0);
    expect(right.value, 100.0);
  });
556 557 558 559 560 561 562 563 564 565

  test('test_updates_collection_is_set', () {
    Param left = new Param.withContext("a");
    Param mid = new Param.withContext("a");
    Param right = new Param.withContext("a");

    Solver s = new Solver();

    expect(s.addEditVariable(mid.variable, Priority.strong), Result.success);

566
    expect(s.addConstraint((mid * cm(2.0)).equals(left + right)),
567
        Result.success);
568
    expect(s.addConstraint(left >= cm(10.0)), Result.success);
569 570 571

    expect(s.suggestValueForVariable(mid.variable, 50.0), Result.success);

572
    Set<dynamic> updates = s.flushUpdates();
573 574 575 576 577 578 579

    expect(updates.length, 1);

    expect(left.value, 10.0);
    expect(mid.value, 50.0);
    expect(right.value, 90.0);
  });
580 581

  test('param_context_non_final', () {
582
    Param p = new Param.withContext("a");
583 584 585
    p.context = "b";
    expect(p.context, "b");
  });
586 587 588 589 590

  test('check_type_of_eq_result', () {
    Param left = new Param();
    Param right = new Param();

591
    expect(left.equals(right).runtimeType, Constraint);
592
  });
593 594 595 596

  test('bulk_add_edit_variables', () {
    Solver s = new Solver();

597 598 599
    Param left = new Param(0.0);
    Param right = new Param(100.0);
    Param mid = new Param(0.0);
600 601

    expect(s.addEditVariables(
602
         <Variable>[left.variable, right.variable, mid.variable], 999.0), Result.success);
603
  });
604 605 606 607

  test('bulk_remove_constraints_and_variables', () {
    Solver s = new Solver();

608 609 610
    Param left = new Param(0.0);
    Param right = new Param(100.0);
    Param mid = new Param(0.0);
611 612

    expect(s.addEditVariables(
613
         <Variable>[left.variable, right.variable, mid.variable], 999.0), Result.success);
614

615 616
    Constraint c1 = left <= mid;
    Constraint c2 = mid <= right;
617

618
    expect(s.addConstraints(<Constraint>[c1, c2]), Result.success);
619

620
    expect(s.removeConstraints(<Constraint>[c1, c2]), Result.success);
621 622

    expect(s.removeEditVariables(
623
                <Variable>[left.variable, right.variable, mid.variable]), Result.success);
624
  });
Chinmay Garde's avatar
Chinmay Garde committed
625
}