// Copyright (c) 2014, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
// Dart test program for testing if statement.

// @dart = 2.9

import "package:expect/expect.dart";

// For logical-or conditions dart2js sometimes inlined expressions, leading to
// completely broken programs.

int globalCounter = 0;

falseWithSideEffect() {
  bool confuse() => new DateTime.now().millisecondsSinceEpoch == 42;

  var result = confuse();

  // Make it harder to inline.
  if (result) {
    try {
      try {
        if (confuse()) falseWithSideEffect();
        if (confuse()) return 499;
      } catch (e) {
        rethrow;
      }
    } catch (e) {
      rethrow;
    }
  }
  globalCounter++;
  return result;
}

falseWithoutSideEffect() {
  bool confuse() => new DateTime.now().millisecondsSinceEpoch == 42;

  var result = confuse();

  // Make it harder to inline.
  if (result) {
    try {
      try {
        if (confuse()) falseWithSideEffect();
        if (confuse()) return 499;
      } catch (e) {
        rethrow;
      }
    } catch (e) {
      rethrow;
    }
  }
  return result;
}

testLogicalOr() {
  globalCounter = 0;
  bool cond1 = falseWithSideEffect();
  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
  Expect.equals(1, globalCounter);

  cond1 = (falseWithSideEffect() == 499);
  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
  if (cond1 || falseWithoutSideEffect()) Expect.fail("must be false");
  Expect.equals(2, globalCounter);
}

List globalList = [];
void testLogicalOr2() {
  globalList.clear();
  testValueOr([]);
  testValueOr(null);
  Expect.listEquals([1, 2, 3], globalList);
}

void testValueOr(List list) {
  if (list == null) globalList.add(1);
  if (list == null || list.contains("2")) globalList.add(2);
  if (list == null || list.contains("3")) globalList.add(3);
}

testLogicalAnd() {
  globalCounter = 0;
  bool cond1 = falseWithSideEffect();
  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
  Expect.equals(1, globalCounter);

  cond1 = (falseWithSideEffect() == 499);
  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
  if (cond1 && falseWithoutSideEffect()) Expect.fail("must be false");
  Expect.equals(2, globalCounter);
}

void testLogicalAnd2() {
  globalList.clear();
  testValueAnd([]);
  testValueAnd(null);
  Expect.listEquals([1, 2, 3], globalList);
}

void testValueAnd(List list) {
  if (list == null) globalList.add(1);
  if (list == null && globalList.contains(1)) globalList.add(2);
  if (list == null && globalList.contains(1)) globalList.add(3);
}

main() {
  testLogicalOr();
  testLogicalOr2();

  testLogicalAnd();
  testLogicalAnd2();
}
