cassowary_test.dart 16.5 KB
Newer Older
Chinmay Garde's avatar
Chinmay Garde committed
1 2 3 4 5 6 7 8 9 10 11 12
// Copyright (c) 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

library cassowary.test;

import 'package:test/test.dart';

import 'package:cassowary/cassowary.dart';

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

  test('variable1', () {
18
    var v = new Param(22.0);
19 20
    expect((v + cm(22.0)).value, 44.0);
    expect((v - cm(20.0)).value, 2.0);
Chinmay Garde's avatar
Chinmay Garde committed
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
  });

  test('term', () {
    var t = new Term(new Variable(22.0), 2.0);
    expect(t.value, 44);
  });

  test('expression', () {
    var terms = [
      new Term(new Variable(22.0), 2.0),
      new Term(new Variable(1.0), 1.0),
    ];
    var e = new Expression(terms, 40.0);
    expect(e.value, 85.0);
  });

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

42
    expect(v1 is Param, true);
43
    expect(v1 + cm(20.0) is Expression, true);
Chinmay Garde's avatar
Chinmay Garde committed
44 45 46 47 48 49 50 51 52 53
    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', () {
54
    var e = new Param(10.0) + cm(5.0);
Chinmay Garde's avatar
Chinmay Garde committed
55 56 57 58
    expect(e.value, 15.0);
    expect(e is Expression, true);

    // Constant
59 60 61 62
    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
63 64 65

    expect(e.value, 15.0);

66 67
    // Param
    var v = new Param(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
68 69 70 71 72 73 74 75
    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
76
    var t = new Term(v.variable, 2.0);
Chinmay Garde's avatar
Chinmay Garde committed
77 78 79 80 81 82 83 84
    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
85
    var e2 = new Param(7.0) + new Param(3.0);
Chinmay Garde's avatar
Chinmay Garde committed
86 87 88 89 90 91 92 93 94 95 96 97
    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', () {
    var t = new Term(new Variable(12.0), 1.0);

    // Constant
98
    var c = cm(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
99 100 101 102 103 104
    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
105
    var v = new Param(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
106 107 108 109 110 111 112 113 114 115 116 117 118
    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
    var t2 = new Term(new Variable(1.0), 2.0);
    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
119
    var exp = new Param(1.0) + cm(1.0);
Chinmay Garde's avatar
Chinmay Garde committed
120 121 122 123 124 125 126
    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', () {
127
    var v = new Param(3.0);
Chinmay Garde's avatar
Chinmay Garde committed
128 129

    // Constant
130
    var c = cm(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
131 132 133 134 135 136
    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
137
    var v2 = new Param(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
138 139 140 141 142 143 144 145 146 147 148 149 150
    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
    var t2 = new Term(new Variable(1.0), 2.0);
    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
151
    var exp = new Param(1.0) + cm(1.0);
Chinmay Garde's avatar
Chinmay Garde committed
152 153 154 155 156 157 158 159 160
    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', () {
161
    var c = cm(3.0);
Chinmay Garde's avatar
Chinmay Garde committed
162 163

    // Constant
164
    var c2 = cm(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
165 166 167 168 169 170
    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
171
    var v2 = new Param(2.0);
Chinmay Garde's avatar
Chinmay Garde committed
172 173 174 175 176 177 178 179 180 181 182 183 184
    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
    var t2 = new Term(new Variable(1.0), 2.0);
    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
185
    var exp = new Param(1.0) + cm(1.0);
Chinmay Garde's avatar
Chinmay Garde committed
186 187 188 189 190 191 192 193

    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', () {
194 195
    var left = new Param(10.0);
    var right = new Param(100.0);
Chinmay Garde's avatar
Chinmay Garde committed
196

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

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

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

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

    // Expression
    var e = new Expression([t], 0.0);
216
    expect((e * cm(2.0)).value, 40.0);
Chinmay Garde's avatar
Chinmay Garde committed
217 218 219 220
  });

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

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

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

    // Expression
    var e = new Expression([t], 0.0);
234
    expect((e / cm(2.0)).value, 10.0);
Chinmay Garde's avatar
Chinmay Garde committed
235 236 237
  });

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

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

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

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

  test('constraint_strength_update', () {
258 259
    var left = new Param(2.0);
    var right = new Param(10.0);
260

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

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

271 272
    var left = new Param(2.0);
    var right = new Param(100.0);
273

274
    var c1 = right - left >= cm(200.0);
275

276 277
    expect((right >= left) is Constraint, true);

278
    expect(s.addConstraint(c1), Result.success);
279 280 281
  });

  test('constraint_complex', () {
282
    var e = new Param(200.0) - new Param(100.0);
283 284

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

    // Variable
291
    var c2 = e >= new Param(2.0);
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310
    expect(c2 is Constraint, true);
    expect(c2.expression.terms.length, 3);
    expect(c2.expression.constant, 0.0);

    // Term
    var c3 = e >= new Term(new Variable(2.0), 1.0);
    expect(c3 is Constraint, true);
    expect(c3.expression.terms.length, 3);
    expect(c3.expression.constant, 0.0);

    // Expression
    var c4 = e >= new Expression([new Term(new Variable(2.0), 1.0)], 20.0);
    expect(c4 is Constraint, true);
    expect(c4.expression.terms.length, 3);
    expect(c4.expression.constant, -20.0);
  });

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

    // Variable
317
    var c2 = new Param(100.0) >= new Param(2.0);
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
    expect(c2 is Constraint, true);
    expect(c2.expression.terms.length, 2);
    expect(c2.expression.constant, 0.0);

    // Term
    var t = new Term(new Variable(100.0), 1.0);
    var c3 = t >= new Term(new Variable(2.0), 1.0);
    expect(c3 is Constraint, true);
    expect(c3.expression.terms.length, 2);
    expect(c3.expression.constant, 0.0);

    // Expression
    var e = new Expression([t], 0.0);
    var c4 = e >= new Expression([new Term(new Variable(2.0), 1.0)], 20.0);
    expect(c4 is Constraint, true);
    expect(c4.expression.terms.length, 2);
    expect(c4.expression.constant, -20.0);
  });
336 337 338 339

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

340 341
    var left = new Param(2.0);
    var right = new Param(100.0);
342

343
    var c1 = right - left >= cm(200.0);
344 345 346 347 348 349 350 351
    var c2 = right >= right;

    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);
  });
352 353

  test('test_multiplication_division_override', () {
354
    var c = cm(10.0);
355 356
    var v = new Param(c.value);
    var t = new Term(v.variable, 1.0);
357 358 359
    var e = new Expression([t], 0.0);

    // Constant
360
    expect((c * cm(10.0)).value, 100);
361 362

    // Variable
363
    expect((v * cm(10.0)).value, 100);
364 365

    // Term
366
    expect((t * cm(10.0)).value, 100);
367 368

    // Expression
369
    expect((e * cm(10.0)).value, 100);
370 371

    // Constant
372
    expect((c / cm(10.0)).value, 1);
373 374

    // Variable
375
    expect((v / cm(10.0)).value, 1);
376 377

    // Term
378
    expect((t / cm(10.0)).value, 1);
379 380

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

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

    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);
  });

401 402 403 404 405 406 407
  test('edit_updates', () {
    Solver s = new Solver();

    var left = new Param(0.0);
    var right = new Param(100.0);
    var mid = new Param(0.0);

408
    Constraint c = left + right >= cm(2.0) * mid;
409 410 411 412 413 414 415 416 417 418 419 420 421 422
    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', () {
    var left = new Param(0.0);
    var right = new Param(100.0);
    var mid = new Param(0.0);

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

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

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

    Solver s = new Solver();

441
    expect(s.addConstraint((right + left).equals(mid * cm(2.0))),
442
        Result.success);
443 444
    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
445

446
    s.flushUpdates();
Chinmay Garde's avatar
Chinmay Garde committed
447 448 449 450 451

    expect(left.value, 0.0);
    expect(mid.value, 50.0);
    expect(right.value, 100.0);
  });
452 453 454 455 456 457 458 459

  test('addition_of_multiple', () {
    var left = new Param(0.0);
    var right = new Param(0.0);
    var mid = new Param(0.0);

    Solver s = new Solver();

460
    var c = (left >= cm(0.0));
461 462

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

468
    expect(s.addConstraints([(right >= cm(-20.0)), c]),
469 470
        Result.duplicateConstraint);
  });
471 472 473 474 475 476 477 478

  test('edit_constraints', () {
    var left = new Param(0.0)..name = "left";
    var right = new Param(0.0)..name = "right";
    var mid = new Param(0.0)..name = "mid";

    Solver s = new Solver();

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

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

487
    s.flushUpdates();
488 489 490 491 492

    expect(left.value, 0.0);
    expect(mid.value, 300.0);
    expect(right.value, 600.0);
  });
493 494 495 496

  test('test_description', () {
    var left = new Param(0.0);
    var right = new Param(100.0);
497 498
    var c1 = right >= left;
    var c2 = right <= left;
499
    var c3 = right.equals(left);
500 501

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

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

  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);

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

526
    solver.flushUpdates();
527 528 529 530 531 532 533

    expect(container.value, 100.0);

    expect(p1.value, 30.0);
    expect(p2.value, 60.0);
    expect(p3.value, 10.0);
  });
534 535

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

    Solver s = new Solver();

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

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

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

550
    var updates = s.flushUpdates();
551 552 553 554 555 556 557

    expect(updates.length, 2);

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

  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);

568
    expect(s.addConstraint((mid * cm(2.0)).equals(left + right)),
569
        Result.success);
570
    expect(s.addConstraint(left >= cm(10.0)), Result.success);
571 572 573 574 575 576 577 578 579 580 581

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

    var updates = s.flushUpdates();

    expect(updates.length, 1);

    expect(left.value, 10.0);
    expect(mid.value, 50.0);
    expect(right.value, 90.0);
  });
582 583 584 585 586 587

  test('param_context_non_final', () {
    var p = new Param.withContext("a");
    p.context = "b";
    expect(p.context, "b");
  });
588 589 590 591 592

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

593
    expect(left.equals(right).runtimeType, Constraint);
594
  });
595 596 597 598 599 600 601 602 603 604 605

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

    var left = new Param(0.0);
    var right = new Param(100.0);
    var mid = new Param(0.0);

    expect(s.addEditVariables(
         [left.variable, right.variable, mid.variable], 999.0), Result.success);
  });
606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626

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

    var left = new Param(0.0);
    var right = new Param(100.0);
    var mid = new Param(0.0);

    expect(s.addEditVariables(
         [left.variable, right.variable, mid.variable], 999.0), Result.success);

    var c1 = left <= mid;
    var c2 = mid <= right;

    expect(s.addConstraints([c1, c2]), Result.success);

    expect(s.removeConstraints([c1, c2]), Result.success);

    expect(s.removeEditVariables(
                [left.variable, right.variable, mid.variable]), Result.success);
  });
Chinmay Garde's avatar
Chinmay Garde committed
627
}