diff --git a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/IndexServlet.java b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/IndexServlet.java index 6551d57e899..06906010ad2 100644 --- a/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/IndexServlet.java +++ b/cloud-sql/mysql/servlet/src/main/java/com/example/cloudsql/IndexServlet.java @@ -105,6 +105,8 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOEx .write( "Unable to successfully cast vote! Please check the application " + "logs for more details."); + // Without this return the success response below overwrites the 500 and the error text. + return; // [END_EXCLUDE] } // [END cloud_sql_mysql_servlet_connection] diff --git a/cloud-sql/mysql/servlet/src/test/java/com/example/cloudsql/TestIndexServletMysqlErrorResponse.java b/cloud-sql/mysql/servlet/src/test/java/com/example/cloudsql/TestIndexServletMysqlErrorResponse.java new file mode 100644 index 00000000000..c19604e9c61 --- /dev/null +++ b/cloud-sql/mysql/servlet/src/test/java/com/example/cloudsql/TestIndexServletMysqlErrorResponse.java @@ -0,0 +1,70 @@ +/* + * Copyright 2024 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.example.cloudsql; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.sql.SQLException; +import java.util.concurrent.atomic.AtomicInteger; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.sql.DataSource; +import org.junit.Test; + +/** Covers the doPost error path, which does not need a database. */ +public class TestIndexServletMysqlErrorResponse { + + @Test + public void testFailedVoteIsNotReportedAsSuccess() throws Exception { + DataSource pool = mock(DataSource.class); + when(pool.getConnection()).thenThrow(new SQLException("connection refused")); + + ServletContext context = mock(ServletContext.class); + when(context.getAttribute("my-pool")).thenReturn(pool); + + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getServletContext()).thenReturn(context); + when(request.getParameter("team")).thenReturn("TABS"); + + StringWriter body = new StringWriter(); + PrintWriter writer = new PrintWriter(body); + AtomicInteger status = new AtomicInteger(); + HttpServletResponse response = mock(HttpServletResponse.class); + when(response.getWriter()).thenReturn(writer); + doAnswer( + invocation -> { + status.set(invocation.getArgument(0)); + return null; + }) + .when(response) + .setStatus(anyInt()); + + new IndexServlet().doPost(request, response); + writer.flush(); + + assertThat(status.get()).isEqualTo(500); + assertThat(body.toString()).contains("Unable to successfully cast vote"); + assertThat(body.toString()).doesNotContain("Vote successfully cast"); + } +} diff --git a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/IndexServlet.java b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/IndexServlet.java index 10e73fd094c..50218c92236 100644 --- a/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/IndexServlet.java +++ b/cloud-sql/postgres/servlet/src/main/java/com/example/cloudsql/IndexServlet.java @@ -123,6 +123,8 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOEx .write( "Unable to successfully cast vote! Please check the application " + "logs for more details."); + // Without this return the success response below overwrites the 500 and the error text. + return; // [END_EXCLUDE] } // [END cloud_sql_postgres_servlet_connection] diff --git a/cloud-sql/postgres/servlet/src/test/java/com/example/cloudsql/TestIndexServletPostgresErrorResponse.java b/cloud-sql/postgres/servlet/src/test/java/com/example/cloudsql/TestIndexServletPostgresErrorResponse.java new file mode 100644 index 00000000000..a255abc20e3 --- /dev/null +++ b/cloud-sql/postgres/servlet/src/test/java/com/example/cloudsql/TestIndexServletPostgresErrorResponse.java @@ -0,0 +1,70 @@ +/* + * Copyright 2024 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.example.cloudsql; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.sql.SQLException; +import java.util.concurrent.atomic.AtomicInteger; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.sql.DataSource; +import org.junit.Test; + +/** Covers the doPost error path, which does not need a database. */ +public class TestIndexServletPostgresErrorResponse { + + @Test + public void testFailedVoteIsNotReportedAsSuccess() throws Exception { + DataSource pool = mock(DataSource.class); + when(pool.getConnection()).thenThrow(new SQLException("connection refused")); + + ServletContext context = mock(ServletContext.class); + when(context.getAttribute("my-pool")).thenReturn(pool); + + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getServletContext()).thenReturn(context); + when(request.getParameter("team")).thenReturn("TABS"); + + StringWriter body = new StringWriter(); + PrintWriter writer = new PrintWriter(body); + AtomicInteger status = new AtomicInteger(); + HttpServletResponse response = mock(HttpServletResponse.class); + when(response.getWriter()).thenReturn(writer); + doAnswer( + invocation -> { + status.set(invocation.getArgument(0)); + return null; + }) + .when(response) + .setStatus(anyInt()); + + new IndexServlet().doPost(request, response); + writer.flush(); + + assertThat(status.get()).isEqualTo(500); + assertThat(body.toString()).contains("Unable to successfully cast vote"); + assertThat(body.toString()).doesNotContain("Vote successfully cast"); + } +} diff --git a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/IndexServlet.java b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/IndexServlet.java index 60aa1ba8621..890ab5254ac 100644 --- a/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/IndexServlet.java +++ b/cloud-sql/sqlserver/servlet/src/main/java/com/example/cloudsql/IndexServlet.java @@ -97,6 +97,8 @@ public void doPost(HttpServletRequest req, HttpServletResponse resp) resp.setStatus(500); resp.getWriter().write("Unable to successfully cast vote! Please check the application " + "logs for more details."); + // Without this return the success response below overwrites the 500 and the error text. + return; // [END_EXCLUDE] } // [END cloud_sql_sqlserver_servlet_connection] diff --git a/cloud-sql/sqlserver/servlet/src/test/java/com/example/cloudsql/TestIndexServletSqlServerErrorResponse.java b/cloud-sql/sqlserver/servlet/src/test/java/com/example/cloudsql/TestIndexServletSqlServerErrorResponse.java new file mode 100644 index 00000000000..dddff5908b1 --- /dev/null +++ b/cloud-sql/sqlserver/servlet/src/test/java/com/example/cloudsql/TestIndexServletSqlServerErrorResponse.java @@ -0,0 +1,70 @@ +/* + * Copyright 2024 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.example.cloudsql; + +import static com.google.common.truth.Truth.assertThat; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.PrintWriter; +import java.io.StringWriter; +import java.sql.SQLException; +import java.util.concurrent.atomic.AtomicInteger; +import javax.servlet.ServletContext; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.sql.DataSource; +import org.junit.Test; + +/** Covers the doPost error path, which does not need a database. */ +public class TestIndexServletSqlServerErrorResponse { + + @Test + public void testFailedVoteIsNotReportedAsSuccess() throws Exception { + DataSource pool = mock(DataSource.class); + when(pool.getConnection()).thenThrow(new SQLException("connection refused")); + + ServletContext context = mock(ServletContext.class); + when(context.getAttribute("my-pool")).thenReturn(pool); + + HttpServletRequest request = mock(HttpServletRequest.class); + when(request.getServletContext()).thenReturn(context); + when(request.getParameter("team")).thenReturn("TABS"); + + StringWriter body = new StringWriter(); + PrintWriter writer = new PrintWriter(body); + AtomicInteger status = new AtomicInteger(); + HttpServletResponse response = mock(HttpServletResponse.class); + when(response.getWriter()).thenReturn(writer); + doAnswer( + invocation -> { + status.set(invocation.getArgument(0)); + return null; + }) + .when(response) + .setStatus(anyInt()); + + new IndexServlet().doPost(request, response); + writer.flush(); + + assertThat(status.get()).isEqualTo(500); + assertThat(body.toString()).contains("Unable to successfully cast vote"); + assertThat(body.toString()).doesNotContain("Vote successfully cast"); + } +}