    @Test
    public void testEnvironmentUpdates() throws Exception {

        // This test ensures the correct propagation of increment/decrement operator side effets through
        // conditional and short-circuiting operators in a value-recoding VariableEnvironment

        // Environment: Create two integer variables x, y with values 5, 10
        VariableEnvironment environment = new VariableEnvironment(null, true);

        ASTNode integerType = TypeContainer.getIntegerType(true, 32);
        Variable varX = createVariable(integerType, "x");
        Variable varY = createVariable(integerType, "y");
        VariableValues varXValues = new VariableValues(varX, 0);
        VariableValues varYValues = new VariableValues(varY, 0);

        IntegerValue initialXValue = new IntegerValue(varX.getType(), 5);
        IntegerValue initialYValue = new IntegerValue(varY.getType(), 10);
        varXValues.addValue(initialXValue);
        varYValues.addValue(initialYValue);

        environment.addVariableValues(varX, varXValues);
        environment.addVariableValues(varY, varYValues);
        environment.finishAddingValues();

        // Prepare expression evaluation
        ExpressionEvaluator expressionEvaluator = new ExpressionEvaluator(null); //null);


        // Build expression "true? ++x: --y"
        Expression xExpression = new Expression(varX);
        Expression yExpression = new Expression(varY);

        Expression trueFirstOperand = new Expression(new BoolValue(true));
        Expression falseFirstOperand = new Expression(new BoolValue(false));

        Expression secondCondOpOperand = new Expression(ASTUnaryOperation.Operator.OP_INC_POST, xExpression);
        Expression thirdCondOpOperand = new Expression(ASTUnaryOperation.Operator.OP_DEC_PRE, yExpression);

        Expression conditionalOperatorFirstBranchTaken = new Expression(trueFirstOperand, secondCondOpOperand, thirdCondOpOperand);
        Expression conditionalOperatorSecondBranchTaken = new Expression(falseFirstOperand, secondCondOpOperand, thirdCondOpOperand);


        //////////////// Process   true? x++: --y    , expecting x to increase by 1 //////////////////////////
        ArrayList<Expression> undoOperations = new ArrayList<Expression>();
        System.out.println("expr " + conditionalOperatorFirstBranchTaken.toASTNode(undoOperations).toSolidityCode());

        ExpressionEvaluator.ComputedValues result;
        result = expressionEvaluator.evaluateForAll(environment, conditionalOperatorFirstBranchTaken);
        // Although the side effect of x++ increments it, the original value must be returned by the expression:
        Assert.assertTrue(      ((IntegerValue)result.values.get(0))  . isEqualTo(initialXValue).getValue());

        // Should have executed ++x, i.e. x=6, y=10
        System.out.println("x value = " + varXValues.getValue(0).toString());
        Assert.assertTrue(varXValues.getValue(0).toString().equals("6"));
        System.out.println("y value = " + varYValues.getValue(0).toString());
        Assert.assertTrue(varYValues.getValue(0).toString().equals("10"));


        //////////////// Process   false? x++: --y    , expecting y to decrease by 1 //////////////////////////

        // Reset to original state, x = 5, y = 10
        undoOperations.clear();
        environment.updateVariableValue(varX, initialXValue);
        environment.updateVariableValue(varY, initialYValue);

        System.out.println("expr " + conditionalOperatorSecondBranchTaken.toASTNode(undoOperations).toSolidityCode());

        result = expressionEvaluator.evaluateForAll(environment, conditionalOperatorSecondBranchTaken);
        // Since a prefix --y is applied, the expression's result must also be 9:
        Assert.assertTrue(      ((IntegerValue)result.values.get(0))  . isEqualTo( ValueContainer.getSmallIntegerValue(varY.getType(), 9)).getValue());

        // Should have executed --y, i.e. x=5, y=9
        System.out.println("x value = " + varXValues.getValue(0).toString());
        Assert.assertTrue(varXValues.getValue(0).toString().equals("5"));
        System.out.println("y value = " + varYValues.getValue(0).toString());
        Assert.assertTrue(varYValues.getValue(0).toString().equals("9"));



        // Build (++x > 0), used as second operand for all subsquent tests
        Expression xGreaterThanZero = new Expression(new Expression(ASTUnaryOperation.Operator.OP_INC_PRE, new Expression(varX)),
                                                    ASTBinaryOperation.Operator.OP_GT,
                                                    new Expression(ValueContainer.getSmallIntegerValue(varX.getType(), 0)));


        //////////////// Process   false && (++x > 0), expecting x not to change //////////////////////////
        undoOperations.clear();
        environment.updateVariableValue(varX, initialXValue); // Start over at 5 again

        Expression logicalAndSecondBranchNotTaken = new Expression(falseFirstOperand,
                                                                    ASTBinaryOperation.Operator.OP_LAND,
                                                                    xGreaterThanZero);

        System.out.println("expr " + logicalAndSecondBranchNotTaken.toASTNode(undoOperations).toSolidityCode());

        result = expressionEvaluator.evaluateForAll(environment, logicalAndSecondBranchNotTaken);
        Assert.assertFalse(((BoolValue)result.values.get(0)).getValue());

        // Should NOT have executed ++x - x = 5 holds
        System.out.println("x value = " + varXValues.getValue(0).toString());
        Assert.assertTrue(varXValues.getValue(0).toString().equals("5"));


        //////////////// Process   true && (++x > 0), expecting x to increase by 1 //////////////////////////
        undoOperations.clear();
        environment.updateVariableValue(varX, initialXValue); // Start over at 5 again

        Expression logicalAndSecondBranchTaken = new Expression(trueFirstOperand,
                ASTBinaryOperation.Operator.OP_LAND,
                xGreaterThanZero);

        result = expressionEvaluator.evaluateForAll(environment, logicalAndSecondBranchTaken);
        Assert.assertTrue(((BoolValue)result.values.get(0)).getValue());

        // Should have executed ++x - x = 6 now
        System.out.println("x value = " + varXValues.getValue(0).toString());
        Assert.assertTrue(varXValues.getValue(0).toString().equals("6"));

        //////////////// Process   true || (++x > 0), expecting x not to change  //////////////////////////
        undoOperations.clear();
        environment.updateVariableValue(varX, initialXValue); // Start over at 5 again

        Expression logicalOrSecondBranchNotTaken = new Expression(trueFirstOperand,
                ASTBinaryOperation.Operator.OP_LOR,
                xGreaterThanZero);

        result = expressionEvaluator.evaluateForAll(environment, logicalOrSecondBranchNotTaken);
        Assert.assertTrue(((BoolValue)result.values.get(0)).getValue());

        // Should NOT have executed ++x - x = 5 still holds
        System.out.println("x value = " + varXValues.getValue(0).toString());
        Assert.assertTrue(varXValues.getValue(0).toString().equals("5"));


        //////////////// Process   false || (++x > 0), expecting x to decrease by 1  //////////////////////////
        undoOperations.clear();
        environment.updateVariableValue(varX, initialXValue); // Start over at 5 again

        Expression logicalOrSecondBranchTaken = new Expression(falseFirstOperand,
                ASTBinaryOperation.Operator.OP_LOR,
                xGreaterThanZero);

        result = expressionEvaluator.evaluateForAll(environment, logicalOrSecondBranchTaken);
        Assert.assertTrue(((BoolValue)result.values.get(0)).getValue());

        // Should have executed ++x - x = 6 now
        System.out.println("x value = " + varXValues.getValue(0).toString());
        Assert.assertTrue(varXValues.getValue(0).toString().equals("6"));
    }