diff --git a/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java b/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java index d2c7f0adad..193ac553c2 100644 --- a/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java +++ b/src/main/java/com/google/api/generator/engine/ast/AstNodeVisitor.java @@ -55,6 +55,8 @@ public interface AstNodeVisitor { public void visit(UnaryOperationExpr unaryOperationExpr); + public void visit(RelationalOperationExpr relationalOperationExpr); + public void visit(LogicalOperationExpr logicalOperationExpr); /** =============================== COMMENT =============================== */ diff --git a/src/main/java/com/google/api/generator/engine/ast/RelationalOperationExpr.java b/src/main/java/com/google/api/generator/engine/ast/RelationalOperationExpr.java new file mode 100644 index 0000000000..cd8bf06766 --- /dev/null +++ b/src/main/java/com/google/api/generator/engine/ast/RelationalOperationExpr.java @@ -0,0 +1,138 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.engine.ast; + +import com.google.auto.value.AutoValue; +import com.google.common.base.Preconditions; + +@AutoValue +public abstract class RelationalOperationExpr implements OperationExpr { + public abstract Expr lhsExpr(); + + public abstract Expr rhsExpr(); + + public abstract OperatorKind operatorKind(); + + @Override + public TypeNode type() { + return TypeNode.BOOLEAN; + } + + @Override + public void accept(AstNodeVisitor visitor) { + visitor.visit(this); + } + + // Convenience wrapper. + public static RelationalOperationExpr equalToWithExprs(Expr lhsExpr, Expr rhsExpr) { + return builder() + .setLhsExpr(lhsExpr) + .setRhsExpr(rhsExpr) + .setOperatorKind(OperatorKind.RELATIONAL_EQUAL_TO) + .build(); + } + + // Convenience wrapper. + public static RelationalOperationExpr notEqualToWithExprs(Expr lhsExpr, Expr rhsExpr) { + return builder() + .setLhsExpr(lhsExpr) + .setRhsExpr(rhsExpr) + .setOperatorKind(OperatorKind.RELATIONAL_NOT_EQUAL_TO) + .build(); + } + + // TODO(summerji): Add convenience wrapper lessThanWithExprs + // public static RelationalOperationExpr lessThanWithExprs(Expr lhsExpr, Expr rhsExpr) { + // return builder() + // .setLhsExpr(lhsExpr) + // .setRhsExpr(rhsExpr) + // .setOperatorKind(OperatorKind.RELATIONAL_LESS_THAN) + // .build(); + // } + + private static Builder builder() { + return new AutoValue_RelationalOperationExpr.Builder(); + } + + @AutoValue.Builder + abstract static class Builder { + + // Private setter. + abstract Builder setLhsExpr(Expr expr); + + // Private setter. + abstract Builder setRhsExpr(Expr expr); + + // Private setter. + abstract Builder setOperatorKind(OperatorKind operator); + + abstract RelationalOperationExpr autoBuild(); + + private RelationalOperationExpr build() { + RelationalOperationExpr relationalOperationExpr = autoBuild(); + TypeNode lhsExprType = relationalOperationExpr.lhsExpr().type(); + TypeNode rhsExprType = relationalOperationExpr.rhsExpr().type(); + OperatorKind operator = relationalOperationExpr.operatorKind(); + final String errorMsg = + String.format( + "Relational operator %s can not be applied to %s, %s.", + operator, lhsExprType.toString(), rhsExprType.toString()); + + if (operator.equals(OperatorKind.RELATIONAL_EQUAL_TO) + || operator.equals(OperatorKind.RELATIONAL_NOT_EQUAL_TO)) { + Preconditions.checkState(isValidEqualityType(lhsExprType, rhsExprType), errorMsg); + } + + return relationalOperationExpr; + } + + // isValidEqualityType checks expressions' type for equality operator (==) and non-equality + // operator (!=). + private boolean isValidEqualityType(TypeNode lhsType, TypeNode rhsType) { + // If the expression's types are matched, return true + if (lhsType.equals(rhsType)) { + return true; + } + + // If the expressions' type are array, the types should be array and matched, or either is + // null type; + if (lhsType.isArray() || rhsType.isArray()) { + return lhsType.equals(TypeNode.NULL) || rhsType.equals(TypeNode.NULL); + } + + // If lhs expression type is numeric type (char, byte, short, int, long, double), the rhs + // expression type should be any numeric type or any numeric boxed type + if (TypeNode.isNumericType(lhsType) && TypeNode.isNumericType(rhsType)) { + return true; + } + + // If lhs expression type is new Object or null, the rhs type should be a reference type or + // null or boxed type; + if (lhsType.equals(TypeNode.OBJECT) || lhsType.equals(TypeNode.NULL)) { + return TypeNode.isReferenceType(rhsType) + || rhsType.equals(TypeNode.OBJECT) + || rhsType.equals(TypeNode.NULL); + } + + // If lhs expression type is Boxed type or a referenced type, rhs should be null or object, + // other cases have been covered in previous conditions. + if (TypeNode.isBoxedType(lhsType) || TypeNode.isReferenceType(lhsType)) { + return rhsType.equals(TypeNode.NULL) || rhsType.equals(TypeNode.OBJECT); + } + + return false; + } + } +} diff --git a/src/main/java/com/google/api/generator/engine/ast/TypeNode.java b/src/main/java/com/google/api/generator/engine/ast/TypeNode.java index adc16f1f26..fbebef1b5d 100644 --- a/src/main/java/com/google/api/generator/engine/ast/TypeNode.java +++ b/src/main/java/com/google/api/generator/engine/ast/TypeNode.java @@ -148,6 +148,10 @@ public static boolean isNumericType(TypeNode type) { || type.equals(TypeNode.CHAR); } + public static boolean isBoxedType(TypeNode type) { + return isReferenceType(type) && BOXED_TYPE_MAP.containsValue(type); + } + public boolean isPrimitiveType() { return isPrimitiveType(typeKind()); } diff --git a/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java b/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java index fadfaaad0d..e59067ec0c 100644 --- a/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java +++ b/src/main/java/com/google/api/generator/engine/writer/ImportWriterVisitor.java @@ -40,6 +40,7 @@ import com.google.api.generator.engine.ast.NewObjectExpr; import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.ReferenceConstructorExpr; +import com.google.api.generator.engine.ast.RelationalOperationExpr; import com.google.api.generator.engine.ast.ReturnExpr; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.Statement; @@ -227,6 +228,12 @@ public void visit(UnaryOperationExpr unaryOperationExpr) { unaryOperationExpr.expr().accept(this); } + @Override + public void visit(RelationalOperationExpr relationalOperationExpr) { + relationalOperationExpr.lhsExpr().accept(this); + relationalOperationExpr.rhsExpr().accept(this); + } + @Override public void visit(LogicalOperationExpr logicalOperationExpr) { logicalOperationExpr.lhsExpr().accept(this); diff --git a/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java b/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java index ff99718c74..5ffed7bdc2 100644 --- a/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java +++ b/src/main/java/com/google/api/generator/engine/writer/JavaWriterVisitor.java @@ -40,6 +40,7 @@ import com.google.api.generator.engine.ast.NewObjectExpr; import com.google.api.generator.engine.ast.OperatorKind; import com.google.api.generator.engine.ast.ReferenceConstructorExpr; +import com.google.api.generator.engine.ast.RelationalOperationExpr; import com.google.api.generator.engine.ast.ReturnExpr; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.Statement; @@ -410,6 +411,15 @@ public void visit(UnaryOperationExpr unaryOperationExpr) { } } + @Override + public void visit(RelationalOperationExpr relationalOperationExpr) { + relationalOperationExpr.lhsExpr().accept(this); + space(); + operator(relationalOperationExpr.operatorKind()); + space(); + relationalOperationExpr.rhsExpr().accept(this); + } + @Override public void visit(LogicalOperationExpr logicalOperationExpr) { logicalOperationExpr.lhsExpr().accept(this); diff --git a/src/test/java/com/google/api/generator/engine/ast/BUILD.bazel b/src/test/java/com/google/api/generator/engine/ast/BUILD.bazel index 9809e2fa11..323b5e1dc1 100644 --- a/src/test/java/com/google/api/generator/engine/ast/BUILD.bazel +++ b/src/test/java/com/google/api/generator/engine/ast/BUILD.bazel @@ -36,6 +36,7 @@ TESTS = [ "WhileStatementTest", "ArithmeticOperationExprTest", "UnaryOperationExprTest", + "RelationalOperationExprTest", "LogicalOperationExprTest", ] diff --git a/src/test/java/com/google/api/generator/engine/ast/RelationalOperationExprTest.java b/src/test/java/com/google/api/generator/engine/ast/RelationalOperationExprTest.java new file mode 100644 index 0000000000..251aadf44a --- /dev/null +++ b/src/test/java/com/google/api/generator/engine/ast/RelationalOperationExprTest.java @@ -0,0 +1,779 @@ +// Copyright 2020 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package com.google.api.generator.engine.ast; + +import static org.junit.Assert.assertThrows; + +import com.google.api.generator.engine.ast.TypeNode.TypeKind; +import org.junit.Test; + +public class RelationalOperationExprTest { + /** ==================== Equality Operators: LHS data type is numeric ======================= */ + @Test + public void equalToOperationExpr_validBasic() { + // LHS: numeric type, RHS: matched numeric type. + // No need swap LHS and RHS test case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validNumericTYpe() { + // LHS: numeric type, RHS: unmatched numeric type. + // No need swap LHS and RHS test case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.CHAR, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.LONG, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void notEqualToOperationExpr_validMatchedNumericBoxTYpe() { + // LHS: numeric type, RHS: matched numeric Boxed type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validBoxedWithMatchedUnBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "y"); + RelationalOperationExpr.notEqualToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void notEqualToOperationExpr_validNumericBoxTYpe() { + // LHS: numeric type, RHS: unmatched numeric Boxed type. + // Swapping LHS and RHS test case is covered in + // equalToOperationExpr_validBoxedWithUnmatchedUnBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "y"); + RelationalOperationExpr.notEqualToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_invalidNumericBooleanBoxedType() { + // LHS: numeric type, RHS: boolean boxed Type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidBoxedBooleanWithNumericType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void notEqualToOperationExpr_invalidNumericStringType() { + // LHS: numeric type, RHS: referenced type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidReferenceWithNumericType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.notEqualToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void notEqualToOperationExpr_invalidNumericNullType() { + // LHS: numeric type, RHS: null. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidNullWithNumericType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.DOUBLE, "x"); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.notEqualToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidNumericBooleanType() { + // LHS: numeric type, RHS: boolean boxed Type. + // Swapping LHS and RHS test case is covered in + // notEqualToOperationExpr_invalidBooleanToNumericType. + VariableExpr lhsExpr = createVariableExpr(TypeNode.LONG, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidNumericTypeWithArrayType() { + // LHS: Numeric Type, RHS: Array with numeric type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidArrayWithNotArrayType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT, "x"); + VariableExpr rhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.INT).build(), "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + /** =============== Equality Operators: LHS data type is numeric boxed type ================ */ + @Test + public void equalToOperationExpr_validBoxedWithMatchedBoxedType() { + // LHS: Boxed type, RHS: Matched Boxed. + // No need swap LHS and RHS test case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + RelationalOperationExpr.equalToWithExprs(rhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validBoxedWithMatchedUnBoxedType() { + // LHS: Boxed type, RHS: Unmatched Boxed. + // Swapping LHS and RHS test case is covered in + // "notEqualToOperationExpr_validMatchedNumericBoxTYpe". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.FLOAT, "y"); + RelationalOperationExpr.equalToWithExprs(rhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validBoxedWithUnmatchedUnBoxedType() { + // LHS: Numeric boxed type, RHS: other numeric type. + // Swapping LHS and RHS test case is covered in "notEqualToOperationExpr_validNumericBoxTYpe". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validNumericBoxedWithNullType() { + // LHS: Boxed type, RHS: Null. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validNullWithNumericBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validNumericBoxedWithNewObjectType() { + // LHS: Numeric boxed type, RHS: new object. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validObjectWithNumericBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + NewObjectExpr rhsExpr = NewObjectExpr.withType(TypeNode.OBJECT); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_invalidNumericBoxedWithBooleanType() { + // LHS: Numeric boxed type, RHS: Boolean type. + // Swapping LHS and RHS test case is covered in + // "notEqualToOperationExpr_invalidBooleanToOtherBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidNumericBoxedWithBooleanBoxedType() { + // LHS: Numeric boxed type, RHS: Boolean Boxed type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidBooleanBoxedWithNumericBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidNumericBoxedWithReferenceType() { + // LHS: Numeric boxed type, RHS: Reference type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidReferenceWithNumericBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.FLOAT_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + /** ============= Equality Operators: LHS data type is boolean or its boxed type ============== */ + @Test + public void equalToOperationExpr_validBooleanType() { + // LHS: boolean type, RHS: boolean Type. + // No need swap LHS and RHS test case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validRHSBooleanBoxedType() { + // LHS: boolean type, RHS: boolean boxed Type. + // Swapping LHS and RHS test case is covered in "equalToOperationExpr_validLHSBooleanBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validLHSBooleanBoxedType() { + // LHS: boolean boxed type, RHS: boolean Type. + // Swapping LHS and RHS test case is covered in "equalToOperationExpr_validRHSBooleanBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void notEqualToOperationExpr_validBooleanBoxedToNullType() { + // LHS: boolean boxed type, RHS: null. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validNullWithBooleanBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "x"); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void notEqualToOperationExpr_validBooleanBoxedToObjectType() { + // LHS: boolean boxed type, RHS: null. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validObjectWithBooleanBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.OBJECT, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void notEqualToOperationExpr_invalidBooleanToNumericType() { + // LHS: boolean type, RHS: char boxed type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidNumericBooleanType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.CHAR, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.notEqualToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void notEqualToOperationExpr_invalidBooleanToOtherBoxedType() { + // LHS: boolean type, RHS: numeric boxed type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidNumericBoxedWithBooleanType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.CHAR_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.notEqualToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void notEqualToOperationExpr_invalidBooleanToReferenceType() { + // LHS: boolean type, RHS: object type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidReferenceWithBooleanType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.notEqualToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidBooleanWithNullType() { + // LHS: boolean type, RHS: null type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidNullWithBooleanType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN, "x"); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidBooleanWithObjectType() { + // LHS: boolean type, RHS: object type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidObjectWithBooleanType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidBoxedBooleanWithNumericType() { + // LHS: boolean boxed type, RHS: numeric + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidNumericBooleanBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidBooleanBoxedWithNumericBoxedType() { + // LHS: boolean boxed type, RHS: numeric + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidNumericBoxedWithBooleanBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidBoxedBooleanWithReferencedType() { + // LHS: boolean boxed type, RHS: reference type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidReferenceWithBooleanBoxedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + /** ===================== Equality Operators: LHS data type is Array ======================== */ + @Test + public void equalToOperationExpr_validArrayWithMatchedType() { + // LHS: Array with numeric type, RHS: Array with matched numeric type. + // No need swap LHS and RHS test case. + VariableExpr lhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.INT).build(), "x"); + VariableExpr rhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.INT).build(), "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validArrayWithNullType() { + // LHS: Array with numeric type, RHS: null + // Swapping LHS and RHS test case is covered in "equalToOperationExpr_validANullWithArrayType". + VariableExpr lhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.INT).build(), "x"); + NullObjectValue nullObjectValue = NullObjectValue.create(); + ValueExpr rhsExpr = ValueExpr.withValue(nullObjectValue); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void notEqualToOperationExpr_invalidArrayWithUnmatchedType() { + // LHS: Array with numeric type, RHS: Array with unmatched numeric type. + // No need swap LHS and RHS test case. + VariableExpr lhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.INT).build(), "x"); + VariableExpr rhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.CHAR).build(), "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.notEqualToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidArrayWithNotArrayType() { + // LHS: Array with numeric type, RHS: not Array + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidNumericTypeWithArrayType". + VariableExpr lhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.INT).build(), "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidArrayWithObjectType() { + // LHS: Array with numeric type, RHS: New Object type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidObjectTypeWithArray". + VariableExpr lhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.INT).build(), "x"); + NewObjectExpr rhsExpr = NewObjectExpr.withType(TypeNode.OBJECT); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + /** ================== Equality Operators: LHS data type is reference type =================== */ + @Test + public void equalToOperationExpr_validReferenceWithMatchedType() { + // LHS: String type, RHS: matched String type. + // No need swap LHS and RHS test case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validReferenceWithNullType() { + // LHS: String type, RHS: null. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validNullWithReferenceType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validReferenceWithObjectType() { + // LHS: String type, RHS: New object type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validObjectWithStringType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + NewObjectExpr rhsExpr = NewObjectExpr.withType(TypeNode.OBJECT); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validAnyObjectTypeWithObject() { + // LHS: Any reference type, RHS: Object type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validObjectWithAnyObjectType". + TypeNode someType = + TypeNode.withReference( + VaporReference.builder() + .setName("SomeClass") + .setPakkage("com.google.api.some.pakkage") + .build()); + VariableExpr lhsExpr = createVariableExpr(someType, "y"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.OBJECT, "x"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validAnyReferenceTypeWithNull() { + // LHS: Any reference type, RHS: Null type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validNullWithAnyReferenceType". + TypeNode someType = + TypeNode.withReference( + VaporReference.builder() + .setName("SomeClass") + .setPakkage("com.google.api.some.pakkage") + .build()); + VariableExpr lhsExpr = createVariableExpr(someType, "y"); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_invalidReferenceWithUnmatchedReferenceType() { + // LHS: String type, RHS: Unmatched reference type. + // No need swap LHS and RHS test case. + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + TypeNode someType = + TypeNode.withReference( + VaporReference.builder() + .setName("SomeClass") + .setPakkage("com.google.api.some.pakkage") + .build()); + VariableExpr rhsExpr = createVariableExpr(someType, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidReferenceWithNumericType() { + // LHS: String type, RHS: Numeric type + // Swapping LHS and RHS test case is covered in + // "notEqualToOperationExpr_invalidNumericStringType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidReferenceWithNumericBoxedType() { + // LHS: String type, RHS: numeric boxed type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidNumericBoxedWithReferenceType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidReferenceWithBooleanType() { + // LHS: String type, RHS: Boolean boxed type. + // Swapping LHS and RHS test case is covered in + // "notEqualToOperationExpr_invalidBooleanToReferenceType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidReferenceWithBooleanBoxedType() { + // LHS: String type, RHS: Boolean boxed type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidBoxedBooleanWithReferencedType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.STRING, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + /** ================== Equality Operators: LHS data type is Object or null =================== */ + @Test + public void equalToOperationExpr_validObjectWithAnyObjectType() { + // LHS: Object type, RHS: Any reference type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validAnyObjectTypeWithObject". + VariableExpr lhsExpr = createVariableExpr(TypeNode.OBJECT, "x"); + TypeNode someType = + TypeNode.withReference( + VaporReference.builder() + .setName("SomeClass") + .setPakkage("com.google.api.some.pakkage") + .build()); + VariableExpr rhsExpr = createVariableExpr(someType, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validNullWithAnyReferenceType() { + // LHS: Null type, RHS: any reference type + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validAnyReferenceTypeWithNull". + ValueExpr lhsExpr = ValueExpr.withValue(NullObjectValue.create()); + TypeNode someType = + TypeNode.withReference( + VaporReference.builder() + .setName("SomeClass") + .setPakkage("com.google.api.some.pakkage") + .build()); + VariableExpr rhsExpr = createVariableExpr(someType, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validObjectWithNullType() { + // LHS: Object, RHS: Null. + // Swapping LHS and RHS test case is covered in "equalToOperationExpr_validNullWithObjectType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.OBJECT, "x"); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validNullWithObjectType() { + // LHS: Null, RHS: Object. + // Swapping LHS and RHS test case is covered in "equalToOperationExpr_validObjectWithNullType". + VariableExpr rhsExpr = createVariableExpr(TypeNode.OBJECT, "x"); + ValueExpr lhsExpr = ValueExpr.withValue(NullObjectValue.create()); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validNullWithNullType() { + // LHS: Null, RHS: Null. + // No need swap LHS and RHS test case. + ValueExpr lhsExpr = ValueExpr.withValue(NullObjectValue.create()); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validObjectWithStringType() { + // LHS: Object type, RHS: Reference type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validReferenceWithObjectType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validObjectWithBooleanBoxedType() { + // LHS: Object type, RHS: Boolean boxed type. + // Swapping LHS and RHS test case is covered in + // "notEqualToOperationExpr_validBooleanBoxedToObjectType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validObjectWithNumericBoxedType() { + // LHS: Object type, RHS: Any Boxed type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validNumericBoxedWithNewObjectType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.SHORT_OBJECT, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validNullWithReferenceType() { + // LHS: Null type, RHS: Reference type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validNullWithReferenceType". + ValueExpr lhsExpr = ValueExpr.withValue(NullObjectValue.create()); + VariableExpr rhsExpr = createVariableExpr(TypeNode.STRING, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validNullWithBooleanBoxedType() { + // LHS: Object type, RHS: Any Boxed type + // Swapping LHS and RHS test case is covered in + // "notEqualToOperationExpr_validBooleanBoxedToNullType". + ValueExpr lhsExpr = ValueExpr.withValue(NullObjectValue.create()); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN_OBJECT, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validNullWithNumericBoxedType() { + // LHS: Object type, RHS: Any Boxed type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_validNumericBoxedWithNullType". + ValueExpr lhsExpr = ValueExpr.withValue(NullObjectValue.create()); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE_OBJECT, "y"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_validANullWithArrayType() { + // LHS: Null, RHS: Array with numeric type. + // Swapping LHS and RHS test case is covered in "equalToOperationExpr_validArrayWithNullType". + NullObjectValue nullObjectValue = NullObjectValue.create(); + ValueExpr lhsExpr = ValueExpr.withValue(nullObjectValue); + VariableExpr rhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.INT).build(), "x"); + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + // No exception thrown, so we succeeded. + } + + @Test + public void equalToOperationExpr_invalidNullWithNumericType() { + // LHS: Null type, RHS: Nny Numeric type. + // Swapping LHS and RHS test case is covered in + // "notEqualToOperationExpr_invalidNumericNullType". + ValueExpr lhsExpr = ValueExpr.withValue(NullObjectValue.create()); + VariableExpr rhsExpr = createVariableExpr(TypeNode.INT, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidNullWithBooleanType() { + // LHS: Null type, RHS: Boolean type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidBooleanWithNullType". + ValueExpr lhsExpr = ValueExpr.withValue(NullObjectValue.create()); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidObjectWithNumericType() { + // LHS: Object type, RHS: Any Numeric type. + VariableExpr lhsExpr = createVariableExpr(TypeNode.OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.DOUBLE, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidObjectWithBooleanType() { + // LHS: Object type, RHS: Boolean type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidBooleanWithObjectType". + VariableExpr lhsExpr = createVariableExpr(TypeNode.OBJECT, "x"); + VariableExpr rhsExpr = createVariableExpr(TypeNode.BOOLEAN, "y"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + @Test + public void equalToOperationExpr_invalidObjectTypeWithArray() { + // LHS: New Object type, RHS: Array with numeric type. + // Swapping LHS and RHS test case is covered in + // "equalToOperationExpr_invalidArrayWithObjectType". + NewObjectExpr lhsExpr = NewObjectExpr.withType(TypeNode.OBJECT); + VariableExpr rhsExpr = + createVariableExpr( + TypeNode.builder().setIsArray(true).setTypeKind(TypeKind.INT).build(), "x"); + assertThrows( + IllegalStateException.class, + () -> RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr)); + } + + private VariableExpr createVariableExpr(TypeNode type, String name) { + Variable variable = Variable.builder().setName(name).setType(type).build(); + VariableExpr variableExpr = VariableExpr.withVariable(variable); + return variableExpr; + } +} diff --git a/src/test/java/com/google/api/generator/engine/ast/TypeNodeTest.java b/src/test/java/com/google/api/generator/engine/ast/TypeNodeTest.java index 5e559db5a7..8462a0cb71 100644 --- a/src/test/java/com/google/api/generator/engine/ast/TypeNodeTest.java +++ b/src/test/java/com/google/api/generator/engine/ast/TypeNodeTest.java @@ -117,4 +117,26 @@ public void invalidType_topLevelWildcard() { assertThrows( IllegalStateException.class, () -> TypeNode.withReference(ConcreteReference.wildcard())); } + + @Test + public void isBoxedType_basic() { + assertTrue(TypeNode.isBoxedType(TypeNode.INT_OBJECT)); + assertTrue(TypeNode.isBoxedType(TypeNode.BOOLEAN_OBJECT)); + assertTrue(TypeNode.isBoxedType(TypeNode.DOUBLE_OBJECT)); + assertTrue( + TypeNode.isBoxedType(TypeNode.withReference(ConcreteReference.withClazz(Long.class)))); + + assertFalse(TypeNode.isBoxedType(TypeNode.BOOLEAN)); + assertFalse(TypeNode.isBoxedType(TypeNode.INT)); + assertFalse(TypeNode.isBoxedType(TypeNode.FLOAT)); + + assertFalse(TypeNode.isBoxedType(TypeNode.STRING)); + TypeNode someType = + TypeNode.withReference( + VaporReference.builder() + .setName("SomeClass") + .setPakkage("com.google.api.generator.engine") + .build()); + assertFalse(TypeNode.isBoxedType(someType)); + } } diff --git a/src/test/java/com/google/api/generator/engine/writer/ImportWriterVisitorTest.java b/src/test/java/com/google/api/generator/engine/writer/ImportWriterVisitorTest.java index d82683a843..352b52379e 100644 --- a/src/test/java/com/google/api/generator/engine/writer/ImportWriterVisitorTest.java +++ b/src/test/java/com/google/api/generator/engine/writer/ImportWriterVisitorTest.java @@ -37,6 +37,7 @@ import com.google.api.generator.engine.ast.NullObjectValue; import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.ReferenceConstructorExpr; +import com.google.api.generator.engine.ast.RelationalOperationExpr; import com.google.api.generator.engine.ast.ReturnExpr; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.SuperObjectValue; @@ -939,6 +940,37 @@ public void writeUnaryOperationExprImports_PostIncrement() { assertEquals(writerVisitor.write(), "import com.google.api.generator.engine.ast.Expr;\n\n"); } + @Test + public void writeRelationalOperationExprImports() { + MethodInvocationExpr lhsExpr = + MethodInvocationExpr.builder() + .setStaticReferenceType(TypeNode.withReference(ConcreteReference.withClazz(Expr.class))) + .setMethodName("getSomething") + .setReturnType(TypeNode.STRING) + .build(); + TypeNode someType = + TypeNode.withReference( + VaporReference.builder() + .setName("SomeClass") + .setPakkage("com.google.api.generator.engine") + .build()); + MethodInvocationExpr rhsExpr = + MethodInvocationExpr.builder() + .setMethodName("getName") + .setStaticReferenceType(someType) + .setReturnType(TypeNode.STRING) + .build(); + RelationalOperationExpr relationalOperationExpr = + RelationalOperationExpr.equalToWithExprs(lhsExpr, rhsExpr); + relationalOperationExpr.accept(writerVisitor); + assertEquals( + writerVisitor.write(), + String.format( + createLines(2), + "import com.google.api.generator.engine.SomeClass;\n", + "import com.google.api.generator.engine.ast.Expr;\n\n")); + } + @Test public void writeLogicalOperationExprImports() { MethodInvocationExpr lhsExpr = diff --git a/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java b/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java index afe36c3430..408f905bd9 100644 --- a/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java +++ b/src/test/java/com/google/api/generator/engine/writer/JavaWriterVisitorTest.java @@ -45,6 +45,7 @@ import com.google.api.generator.engine.ast.PrimitiveValue; import com.google.api.generator.engine.ast.Reference; import com.google.api.generator.engine.ast.ReferenceConstructorExpr; +import com.google.api.generator.engine.ast.RelationalOperationExpr; import com.google.api.generator.engine.ast.ReturnExpr; import com.google.api.generator.engine.ast.ScopeNode; import com.google.api.generator.engine.ast.Statement; @@ -2058,6 +2059,45 @@ public void writeUnaryOperationExpr_logicalNot() { assertThat(writerVisitor.write()).isEqualTo("!isEmpty()"); } + @Test + public void writeRelationalOperationExpr_equalTo() { + VariableExpr variableExprLHS = + VariableExpr.withVariable( + Variable.builder().setType(TypeNode.BOOLEAN_OBJECT).setName("isGood").build()); + MethodInvocationExpr methodInvocationExpr = + MethodInvocationExpr.builder() + .setMethodName("isBad") + .setReturnType(TypeNode.BOOLEAN) + .build(); + + RelationalOperationExpr equalToOperationExpr = + RelationalOperationExpr.equalToWithExprs(variableExprLHS, methodInvocationExpr); + equalToOperationExpr.accept(writerVisitor); + assertThat(writerVisitor.write()).isEqualTo("isGood == isBad()"); + } + + @Test + public void writeRelationOperationExpr_notEqualTo() { + TypeNode someType = + TypeNode.withReference( + VaporReference.builder() + .setName("SomeClass") + .setPakkage("com.google.api.generator.engine") + .build()); + MethodInvocationExpr lhsExpr = + MethodInvocationExpr.builder() + .setMethodName("getName") + .setStaticReferenceType(someType) + .setReturnType(TypeNode.STRING) + .build(); + ValueExpr rhsExpr = ValueExpr.withValue(NullObjectValue.create()); + + RelationalOperationExpr notEqualToOperationExpr = + RelationalOperationExpr.notEqualToWithExprs(lhsExpr, rhsExpr); + notEqualToOperationExpr.accept(writerVisitor); + assertThat(writerVisitor.write()).isEqualTo("SomeClass.getName() != null"); + } + @Test public void writeLogicalOperationExpr_logicalAnd() { VariableExpr lhsExpr = VariableExpr.withVariable(createVariable("isEmpty", TypeNode.BOOLEAN));