/*
 * Copyright 2009-present MongoDB, Inc.
 *
 * 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.
 */

#include <mongoc/mongoc-client-private.h>

#include <mongoc/mongoc.h>

#include <mlib/config.h>

#include <TestSuite.h>
#include <mock_server/future-functions.h>
#include <mock_server/mock-server.h>
#include <test-conveniences.h>
#include <test-libmongoc.h>


static void
test_mongos_hedged_reads_read_pref(void)
{
   mock_server_t *server;
   mongoc_collection_t *collection;
   mongoc_client_t *client;
   bson_t hedge_doc = BSON_INITIALIZER;
   mongoc_read_prefs_t *prefs;
   future_t *future;
   request_t *request;
   bson_error_t error;

   server = mock_mongos_new(WIRE_VERSION_MIN);
   mock_server_run(server);
   mock_server_auto_endsessions(server);
   client = test_framework_client_new_from_uri(mock_server_get_uri(server), NULL);
   collection = mongoc_client_get_collection(client, "db", "collection");

   prefs = mongoc_read_prefs_new(MONGOC_READ_SECONDARY_PREFERRED);

   /* For all read preference modes that are not 'primary', drivers MUST set
    * readPreference. */
   mongoc_collection_set_read_prefs(collection, prefs);

   future = future_collection_estimated_document_count(collection, NULL, prefs, NULL, &error);
   request = mock_server_receives_msg(server,
                                      MONGOC_MSG_NONE,
                                      tmp_bson("{'$db': 'db',"
                                               " '$readPreference': {'mode': 'secondaryPreferred'}}"));

   reply_to_request_simple(request, "{'ok': 1, 'n': 1}");
   ASSERT_OR_PRINT(1 == future_get_int64_t(future), error);

   request_destroy(request);
   future_destroy(future);

   /* CDRIVER-3583:
    * with readPreference mode secondaryPreferred and hedge set, readPreference
    * MUST be sent. */
   bson_append_bool(&hedge_doc, "enabled", 7, true);

   mlib_diagnostic_push();
   mlib_disable_deprecation_warnings();
   mongoc_read_prefs_set_hedge(prefs, &hedge_doc);
   mlib_diagnostic_pop();

   mongoc_collection_set_read_prefs(collection, prefs);

   future = future_collection_estimated_document_count(collection, NULL, prefs, NULL, &error);
   request = mock_server_receives_msg(server,
                                      MONGOC_MSG_NONE,
                                      tmp_bson("{'$db': 'db',"
                                               " '$readPreference': {"
                                               "   'mode': 'secondaryPreferred',"
                                               "   'hedge': {'enabled': true}}}"));

   reply_to_request_simple(request, "{'ok': 1, 'n': 1}");
   ASSERT_OR_PRINT(1 == future_get_int64_t(future), error);

   request_destroy(request);
   future_destroy(future);

   mongoc_read_prefs_destroy(prefs);
   bson_destroy(&hedge_doc);
   mongoc_collection_destroy(collection);
   mongoc_client_destroy(client);
   mock_server_destroy(server);
}


void
test_client_hedged_reads_install(TestSuite *suite)
{
   TestSuite_AddMockServerTest(suite, "/Client/hedged_reads/mongos", test_mongos_hedged_reads_read_pref);
}
