agones.dev/agones@v1.54.0/test/sdk/rust/src/main.rs (about)

     1  // Copyright 2018 Google LLC All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  use std::{env, thread, time::Duration};
    16  
    17  #[tokio::main(flavor = "multi_thread", worker_threads = 4)]
    18  async fn main() {
    19      println!("Rust Game Server has started!");
    20  
    21      ::std::process::exit(match run().await {
    22          Ok(_) => {
    23              println!("Rust Game Server finished.");
    24              0
    25          }
    26          Err(msg) => {
    27              println!("rust: {}", msg);
    28              1
    29          }
    30      });
    31  }
    32  
    33  async fn run() -> Result<(), String> {
    34      let env_run_async = env::var("RUN_ASYNC").unwrap_or_default();
    35      if env_run_async.contains("true") {
    36          println!("rust: RUN_ASYNC is set to true, so run test for async functions");
    37          run_async().await
    38      } else {
    39          tokio::task::block_in_place(run_sync)
    40      }
    41  }
    42  
    43  fn run_sync() -> Result<(), String> {
    44      use tokio::runtime::Handle;
    45  
    46      println!("rust: Creating SDK instance");
    47      let mut sdk = Handle::current().block_on(async move {
    48          agones::Sdk::new(None /* default port */, None /* keep_alive */)
    49              .await
    50              .map_err(|e| format!("unable to create sdk client: {}", e))
    51      })?;
    52  
    53      // Spawn a task that will send health checks every 2 seconds. If this current
    54      // thread/task panics or dropped, the health check will also be stopped
    55      let _health = {
    56          let health_tx = sdk.health_check();
    57          let (tx, mut rx) = tokio::sync::oneshot::channel::<()>();
    58  
    59          Handle::current().spawn(async move {
    60              let mut interval = tokio::time::interval(Duration::from_secs(2));
    61  
    62              loop {
    63                  tokio::select! {
    64                      _ = interval.tick() => {
    65                          if health_tx
    66                              .send(())
    67                              .await.is_err() {
    68                              eprintln!("Health check receiver was dropped");
    69                              break;
    70                          }
    71                      }
    72                      _ = &mut rx => {
    73                          println!("Health check task canceled");
    74                          break;
    75                      }
    76                  }
    77              }
    78          });
    79  
    80          tx
    81      };
    82  
    83      let _watch = {
    84          let mut watch_client = sdk.clone();
    85          let (tx, mut rx) = tokio::sync::oneshot::channel::<()>();
    86  
    87          tokio::task::spawn(async move {
    88              println!("rust: Starting to watch GameServer updates...");
    89              let mut once = true;
    90              match watch_client.watch_gameserver().await {
    91                  Err(e) => eprintln!("rust: Failed to watch for GameServer updates: {}", e),
    92                  Ok(mut stream) => loop {
    93                      tokio::select! {
    94                          gs = stream.message() => {
    95                              match gs {
    96                                  Ok(Some(gs)) => {
    97                                      let om = gs.object_meta.unwrap();
    98                                      println!("rust: GameServer Update, name: {}", om.name);
    99                                      println!("rust: GameServer Update, state: {}", gs.status.unwrap().state);
   100  
   101                                      if once {
   102                                          println!("rust: Setting an annotation");
   103                                          let uid = om.uid.clone();
   104  
   105                                          if let Err(e) = watch_client.set_annotation("test-annotation", uid).await {
   106                                              eprintln!("rust: Failed to set annotation from watch task: {}", e);
   107                                          }
   108  
   109                                          once = false;
   110                                      }
   111                                  }
   112                                  Ok(None) => {
   113                                      println!("rust: Server closed the GameServer watch stream");
   114                                      break;
   115                                  }
   116                                  Err(e) => {
   117                                      eprintln!("rust: GameServer Update stream encountered an error: {}", e);
   118                                  }
   119                              }
   120  
   121                          }
   122                          _ = &mut rx => {
   123                              println!("rust: Shutting down GameServer watch loop");
   124                              break;
   125                          }
   126                      }
   127                  },
   128              }
   129          });
   130  
   131          tx
   132      };
   133  
   134      // Waiting for a thread to spawn
   135      thread::sleep(Duration::from_secs(2));
   136  
   137      println!("rust: Marking server as ready...");
   138      Handle::current().block_on(async {
   139          sdk.ready()
   140              .await
   141              .map_err(|e| format!("Could not run Ready(): {}. Exiting!", e))
   142      })?;
   143  
   144      println!("rust: ...marked Ready");
   145  
   146      println!("rust: Reserving for 5 seconds");
   147      Handle::current().block_on(async {
   148          sdk.reserve(Duration::from_secs(5))
   149              .await
   150              .map_err(|e| format!("Could not run Reserve(): {}. Exiting!", e))
   151      })?;
   152      println!("rust: ...Reserved");
   153  
   154      println!("rust: Allocate game server ...");
   155      Handle::current().block_on(async {
   156          sdk.allocate()
   157              .await
   158              .map_err(|e| format!("Could not run Allocate(): {}. Exiting!", e))
   159      })?;
   160  
   161      println!("rust: ...marked Allocated");
   162  
   163      println!("rust: Getting GameServer details...");
   164      let gameserver = Handle::current().block_on(async {
   165          sdk.get_gameserver()
   166              .await
   167              .map_err(|e| format!("Could not run GameServer(): {}. Exiting!", e))
   168      })?;
   169  
   170      println!(
   171          "rust: GameServer name: {}",
   172          gameserver.object_meta.clone().unwrap().name
   173      );
   174  
   175      println!("rust: Setting a label");
   176      let creation_ts = gameserver.object_meta.unwrap().creation_timestamp;
   177      Handle::current().block_on(async {
   178          sdk.set_label("test-label", &creation_ts.to_string())
   179              .await
   180              .map_err(|e| format!("Could not run SetLabel(): {}. Exiting!", e))
   181      })?;
   182  
   183      let feature_gates = env::var("FEATURE_GATES").unwrap_or_default();
   184      if feature_gates.contains("PlayerTracking=true") {
   185          run_player_tracking_features(sdk.alpha().clone())?;
   186      }
   187      if feature_gates.contains("CountsAndLists=true") {
   188          run_counts_and_lists_features(sdk.beta().clone())?;
   189      }
   190  
   191      for i in 0..1 {
   192          let time = i * 5;
   193          println!("rust: Running for {} seconds", time);
   194  
   195          thread::sleep(Duration::from_secs(5));
   196      }
   197  
   198      println!("rust: Shutting down...");
   199      Handle::current().block_on(async {
   200          sdk.shutdown()
   201              .await
   202              .map_err(|e| format!("Could not run Shutdown: {}. Exiting!", e))
   203      })?;
   204      println!("rust: ...marked for Shutdown");
   205  
   206      Ok(())
   207  }
   208  
   209  fn run_player_tracking_features(mut alpha: agones::alpha::Alpha) -> Result<(), String> {
   210      use tokio::runtime::Handle;
   211  
   212      println!("rust: Setting player capacity...");
   213      Handle::current().block_on(async {
   214          alpha
   215              .set_player_capacity(10)
   216              .await
   217              .map_err(|e| format!("Could not run SetPlayerCapacity(): {:#?}. Exiting!", e))
   218      })?;
   219  
   220      println!("rust: Getting player capacity...");
   221      let capacity = Handle::current().block_on(async {
   222          alpha
   223              .get_player_capacity()
   224              .await
   225              .map_err(|e| format!("Could not run GetPlayerCapacity(): {}. Exiting!", e))
   226      })?;
   227      println!("rust: Player capacity: {}", capacity);
   228  
   229      println!("rust: Increasing the player count...");
   230      let player_id = "1234".to_string();
   231  
   232      let added = Handle::current().block_on(async {
   233          alpha
   234              .player_connect(&player_id)
   235              .await
   236              .map_err(|e| format!("Could not run PlayerConnect(): {}. Exiting!", e))
   237      })?;
   238      if added {
   239          println!("rust: Added player");
   240      } else {
   241          panic!("rust: Failed to add player. Exiting!");
   242      }
   243  
   244      let connected = Handle::current().block_on(async {
   245          alpha
   246              .is_player_connected(&player_id)
   247              .await
   248              .map_err(|e| format!("Could not run IsPlayerConnected(): {}. Exiting!", e))
   249      })?;
   250      if connected {
   251          println!("rust: {} is connected", player_id);
   252      } else {
   253          panic!("rust: {} is not connected. Exiting!", player_id);
   254      }
   255  
   256      let player_ids = Handle::current().block_on(async {
   257          alpha
   258              .get_connected_players()
   259              .await
   260              .map_err(|e| format!("Could not run GetConnectedPlayers(): {}. Exiting!", e))
   261      })?;
   262      println!("rust: Connected players: {:?}", player_ids);
   263  
   264      let player_count = Handle::current().block_on(async {
   265          alpha
   266              .get_player_count()
   267              .await
   268              .map_err(|e| format!("Could not run GetConnectedPlayers(): {}. Exiting!", e))
   269      })?;
   270      println!("rust: Current player count: {}", player_count);
   271  
   272      println!("rust: Decreasing the player count...");
   273      let removed = Handle::current().block_on(async {
   274          alpha
   275              .player_disconnect(&player_id)
   276              .await
   277              .map_err(|e| format!("Could not run PlayerDisconnect(): {}. Exiting!", e))
   278      })?;
   279      if removed {
   280          println!("rust: Removed player");
   281      } else {
   282          panic!("rust: Failed to remove player. Exiting!");
   283      }
   284  
   285      let player_count = Handle::current().block_on(async {
   286          alpha
   287              .get_player_count()
   288              .await
   289              .map_err(|e| format!("Could not GetPlayerCount(): {}. Exiting!", e))
   290      })?;
   291      println!("rust: Current player count: {}", player_count);
   292  
   293      Ok(())
   294  }
   295  
   296  fn run_counts_and_lists_features(mut beta: agones::beta::Beta) -> Result<(), String> {
   297      use tokio::runtime::Handle;
   298  
   299      // Counter tests
   300      let counter = "rooms";
   301      println!("rust: Getting Counter count...");
   302      let count = Handle::current().block_on(async {
   303          beta.get_counter_count(counter)
   304              .await
   305              .map_err(|e| format!("Could not run GetCounterCount(): {}. Exiting!", e))
   306      })?;
   307      if count != 1 {
   308          return Err(format!("Counter count should be 1, but is {}", count));
   309      }
   310  
   311      println!("rust: Incrementing Counter...");
   312      Handle::current().block_on(async {
   313          beta.increment_counter(counter, 9)
   314              .await
   315              .map_err(|e| format!("Could not run IncrementCounter(): {}. Exiting!", e))
   316      })?;
   317  
   318      println!("rust: Decrementing Counter...");
   319      Handle::current().block_on(async {
   320          beta.decrement_counter(counter, 10)
   321              .await
   322              .map_err(|e| format!("Could not run DecrementCounter(): {}. Exiting!", e))
   323      })?;
   324  
   325      println!("rust: Setting Counter count...");
   326      Handle::current().block_on(async {
   327          beta.set_counter_count(counter, 10)
   328              .await
   329              .map_err(|e| format!("Could not run SetCounterCount(): {}. Exiting!", e))
   330      })?;
   331  
   332      println!("rust: Getting Counter capacity...");
   333      let capacity = Handle::current().block_on(async {
   334          beta.get_counter_capacity(counter)
   335              .await
   336              .map_err(|e| format!("Could not run GetCounterCapacity(): {}. Exiting!", e))
   337      })?;
   338      if capacity != 10 {
   339          return Err(format!("Counter capacity should be 10, but is {}", capacity));
   340      }
   341  
   342      println!("rust: Setting Counter capacity...");
   343      Handle::current().block_on(async {
   344          beta.set_counter_capacity(counter, 1)
   345              .await
   346              .map_err(|e| format!("Could not run SetCounterCapacity(): {}. Exiting!", e))
   347      })?;
   348  
   349      // List tests
   350      let list = "players";
   351      let vals = vec!["test0".to_string(), "test1".to_string(), "test2".to_string()];
   352  
   353      println!("rust: Checking if List contains 'test1'...");
   354      let contains = Handle::current().block_on(async {
   355          beta.list_contains(list, "test1")
   356              .await
   357              .map_err(|e| format!("Could not run ListContains(): {}. Exiting!", e))
   358      })?;
   359      if !contains {
   360          return Err("List should contain value \"test1\"".to_string());
   361      }
   362  
   363      println!("rust: Getting List length...");
   364      let length = Handle::current().block_on(async {
   365          beta.get_list_length(list)
   366              .await
   367              .map_err(|e| format!("Could not run GetListLength(): {}. Exiting!", e))
   368      })?;
   369      if length != 3 {
   370          return Err(format!("List length should be 3, but is {}", length));
   371      }
   372  
   373      println!("rust: Getting List values...");
   374      let values = Handle::current().block_on(async {
   375          beta.get_list_values(list)
   376              .await
   377              .map_err(|e| format!("Could not run GetListValues(): {}. Exiting!", e))
   378      })?;
   379      if values != vals {
   380          return Err(format!("List values should be {:?}, but is {:?}", vals, values));
   381      }
   382  
   383      println!("rust: Appending value 'test3' to List...");
   384      Handle::current().block_on(async {
   385          beta.append_list_value(list, "test3")
   386              .await
   387              .map_err(|e| format!("Could not run AppendListValue(): {}. Exiting!", e))
   388      })?;
   389  
   390      println!("rust: Deleting value 'test2' from List...");
   391      Handle::current().block_on(async {
   392          beta.delete_list_value(list, "test2")
   393              .await
   394              .map_err(|e| format!("Could not run DeleteListValue(): {}. Exiting!", e))
   395      })?;
   396  
   397      println!("rust: Getting List capacity...");
   398  
   399      Ok(())
   400  }
   401  
   402  
   403  async fn run_async() -> Result<(), String> {
   404      let mut sdk = match tokio::time::timeout(
   405          Duration::from_secs(30),
   406          agones::Sdk::new(None /* default port */, None /* keep_alive */),
   407      )
   408      .await
   409      {
   410          Ok(sdk) => sdk.map_err(|e| format!("unable to create sdk client: {}", e))?,
   411          Err(_) => return Err("timed out attempting to connect to the sidecar".to_owned()),
   412      };
   413  
   414      let _health = {
   415          let health_tx = sdk.health_check();
   416          let (tx, mut rx) = tokio::sync::oneshot::channel::<()>();
   417  
   418          tokio::task::spawn(async move {
   419              let mut interval = tokio::time::interval(Duration::from_secs(2));
   420  
   421              loop {
   422                  tokio::select! {
   423                      _ = interval.tick() => {
   424                          if health_tx
   425                              .send(())
   426                              .await.is_err() {
   427                              eprintln!("Health check receiver was dropped");
   428                              break;
   429                          }
   430                      }
   431                      _ = &mut rx => {
   432                          println!("Health check task canceled");
   433                          break;
   434                      }
   435                  }
   436              }
   437          });
   438  
   439          tx
   440      };
   441  
   442      let _watch = {
   443          let mut watch_client = sdk.clone();
   444          let (tx, mut rx) = tokio::sync::oneshot::channel::<()>();
   445  
   446          tokio::task::spawn(async move {
   447              println!("rust_async: Starting to watch GameServer updates...");
   448              let mut once = true;
   449              match watch_client.watch_gameserver().await {
   450                  Err(e) => eprintln!("rust_async: Failed to watch for GameServer updates: {}", e),
   451                  Ok(mut stream) => loop {
   452                      tokio::select! {
   453                          gs = stream.message() => {
   454                              match gs {
   455                                  Ok(Some(gs)) => {
   456                                      let om = gs.object_meta.unwrap();
   457                                      println!("rust_async: GameServer Update, name: {}", om.name);
   458                                      println!("rust_async: GameServer Update, state: {}", gs.status.unwrap().state);
   459  
   460                                      if once {
   461                                          println!("rust_async: Setting an annotation");
   462                                          let uid = om.uid.clone();
   463  
   464                                          if let Err(e) = watch_client.set_annotation("test-annotation", uid).await {
   465                                              eprintln!("rust_async: Failed to set annotation from watch task: {}", e);
   466                                          }
   467  
   468                                          once = false;
   469                                      }
   470                                  }
   471                                  Ok(None) => {
   472                                      println!("rust_async: Server closed the GameServer watch stream");
   473                                      break;
   474                                  }
   475                                  Err(e) => {
   476                                      eprintln!("rust_async: GameServer Update stream encountered an error: {}", e);
   477                                  }
   478                              }
   479  
   480                          }
   481                          _ = &mut rx => {
   482                              println!("rust_async: Shutting down GameServer watch loop");
   483                              break;
   484                          }
   485                      }
   486                  },
   487              }
   488          });
   489  
   490          tx
   491      };
   492  
   493      tokio::time::sleep(Duration::from_secs(2)).await;
   494  
   495      println!("rust_async: Marking server as ready...");
   496      sdk.ready()
   497          .await
   498          .map_err(|e| format!("Could not run Ready(): {}. Exiting!", e))?;
   499      println!("rust_async: ...marked Ready");
   500  
   501      println!("rust_async: Reserving for 5 seconds");
   502      sdk.reserve(Duration::new(5, 0))
   503          .await
   504          .map_err(|e| format!("Could not run Reserve(): {}. Exiting!", e))?;
   505      println!("rust_async: ...Reserved");
   506  
   507      println!("rust_async: Allocate game server ...");
   508      sdk.allocate()
   509          .await
   510          .map_err(|e| format!("Could not run Allocate(): {}. Exiting!", e))?;
   511  
   512      println!("rust_async: ...marked Allocated");
   513  
   514      println!("rust_async: Getting GameServer details...");
   515      let gameserver = sdk
   516          .get_gameserver()
   517          .await
   518          .map_err(|e| format!("Could not run GameServer(): {}. Exiting!", e))?;
   519  
   520      println!(
   521          "rust_async: GameServer name: {}",
   522          gameserver.object_meta.clone().unwrap().name
   523      );
   524  
   525      println!("rust_async: Setting a label");
   526      let creation_ts = gameserver.object_meta.clone().unwrap().creation_timestamp;
   527      sdk.set_label("test-label", &creation_ts.to_string())
   528          .await
   529          .map_err(|e| format!("Could not run SetLabel(): {}. Exiting!", e))?;
   530  
   531      let feature_gates = env::var("FEATURE_GATES").unwrap_or_default();
   532      if feature_gates.contains("PlayerTracking=true") {
   533          run_player_tracking_features_async(sdk.alpha().clone()).await?;
   534      }
   535      if feature_gates.contains("CountsAndLists=true") {
   536          run_counts_and_lists_features_async(sdk.beta().clone()).await?;
   537      }
   538  
   539      for i in 0..1 {
   540          let time = i * 5;
   541          println!("rust_async: Running for {} seconds", time);
   542  
   543          tokio::time::sleep(Duration::from_secs(5)).await;
   544      }
   545  
   546      println!("rust_async: Shutting down...");
   547      sdk.shutdown()
   548          .await
   549          .map_err(|e| format!("Could not run Shutdown: {}. Exiting!", e))?;
   550      println!("rust_async: ...marked for Shutdown");
   551  
   552      Ok(())
   553  }
   554  
   555  async fn run_player_tracking_features_async(mut alpha: agones::alpha::Alpha) -> Result<(), String> {
   556      println!("rust_async: Setting player capacity...");
   557      alpha
   558          .set_player_capacity(10)
   559          .await
   560          .map_err(|e| format!("Could not run SetPlayerCapacity(): {}. Exiting!", e))?;
   561  
   562      println!("rust_async: Getting player capacity...");
   563      let capacity = alpha
   564          .get_player_capacity()
   565          .await
   566          .map_err(|e| format!("Could not run GetPlayerCapacity(): {}. Exiting!", e))?;
   567      println!("rust_async: Player capacity: {}", capacity);
   568  
   569      println!("rust_async: Increasing the player count...");
   570      let player_id = "1234".to_string();
   571      let added = alpha
   572          .player_connect(&player_id)
   573          .await
   574          .map_err(|e| format!("Could not run PlayerConnect(): {}. Exiting!", e))?;
   575      if added {
   576          println!("Added player");
   577      } else {
   578          panic!("rust_async: Failed to add player. Exiting!");
   579      }
   580  
   581      let connected = alpha
   582          .is_player_connected(&player_id)
   583          .await
   584          .map_err(|e| format!("Could not run IsPlayerConnected(): {}. Exiting!", e))?;
   585      if connected {
   586          println!("rust_async: {} is connected", player_id);
   587      } else {
   588          panic!("rust_async: {} is not connected. Exiting!", player_id);
   589      }
   590  
   591      let player_ids = alpha
   592          .get_connected_players()
   593          .await
   594          .map_err(|e| format!("Could not run GetConnectedPlayers(): {}. Exiting!", e))?;
   595      println!("rust_async: Connected players: {:?}", player_ids);
   596  
   597      let player_count = alpha
   598          .get_player_count()
   599          .await
   600          .map_err(|e| format!("Could not run GetConnectedPlayers(): {}. Exiting!", e))?;
   601      println!("rust_async: Current player count: {}", player_count);
   602  
   603      println!("rust_async: Decreasing the player count...");
   604      let removed = alpha
   605          .player_disconnect(&player_id)
   606          .await
   607          .map_err(|e| format!("Could not run PlayerDisconnect(): {}. Exiting!", e))?;
   608      if removed {
   609          println!("rust_async: Removed player");
   610      } else {
   611          panic!("rust_async: Failed to remove player. Exiting!");
   612      }
   613  
   614      let player_count = alpha
   615          .get_player_count()
   616          .await
   617          .map_err(|e| format!("Could not GetPlayerCount(): {}. Exiting!", e))?;
   618      println!("rust_async: Current player count: {}", player_count);
   619  
   620      Ok(())
   621  }
   622  
   623  async fn run_counts_and_lists_features_async(mut beta: agones::beta::Beta) -> Result<(), String> {
   624      // Counter tests
   625      let counter = "rooms";
   626      println!("rust_async: Getting Counter count...");
   627      let count = beta.get_counter_count(counter)
   628          .await
   629          .map_err(|e| format!("Could not run GetCounterCount(): {}. Exiting!", e))?;
   630      if count != 1 {
   631          return Err(format!("Counter count should be 1, but is {}", count));
   632      }
   633  
   634      println!("rust_async: Incrementing Counter...");
   635      beta.increment_counter(counter, 9)
   636          .await
   637          .map_err(|e| format!("Could not run IncrementCounter(): {}. Exiting!", e))?;
   638  
   639      println!("rust_async: Decrementing Counter...");
   640      beta.decrement_counter(counter, 10)
   641          .await
   642          .map_err(|e| format!("Could not run DecrementCounter(): {}. Exiting!", e))?;
   643  
   644      println!("rust_async: Setting Counter count...");
   645      beta.set_counter_count(counter, 10)
   646          .await
   647          .map_err(|e| format!("Could not run SetCounterCount(): {}. Exiting!", e))?;
   648  
   649      println!("rust_async: Getting Counter capacity...");
   650      let capacity = beta.get_counter_capacity(counter)
   651          .await
   652          .map_err(|e| format!("Could not run GetCounterCapacity(): {}. Exiting!", e))?;
   653      if capacity != 10 {
   654          return Err(format!("Counter capacity should be 10, but is {}", capacity));
   655      }
   656  
   657      println!("rust_async: Setting Counter capacity...");
   658      beta.set_counter_capacity(counter, 1)
   659          .await
   660          .map_err(|e| format!("Could not run SetCounterCapacity(): {}. Exiting!", e))?;
   661  
   662      // List tests
   663      let list = "players";
   664      let vals = vec!["test0".to_string(), "test1".to_string(), "test2".to_string()];
   665  
   666      println!("rust_async: Checking if List contains 'test1'...");
   667      let contains = beta.list_contains(list, "test1")
   668          .await
   669          .map_err(|e| format!("Could not run ListContains(): {}. Exiting!", e))?;
   670      if !contains {
   671          return Err("List should contain value \"test1\"".to_string());
   672      }
   673  
   674      println!("rust_async: Getting List length...");
   675      let length = beta.get_list_length(list)
   676          .await
   677          .map_err(|e| format!("Could not run GetListLength(): {}. Exiting!", e))?;
   678      if length != 3 {
   679          return Err(format!("List length should be 3, but is {}", length));
   680      }
   681  
   682      println!("rust_async: Getting List values...");
   683      let values = beta.get_list_values(list)
   684          .await
   685          .map_err(|e| format!("Could not run GetListValues(): {}. Exiting!", e))?;
   686      if values != vals {
   687          return Err(format!("List values should be {:?}, but is {:?}", vals, values));
   688      }
   689  
   690      println!("rust_async: Appending value 'test3' to List...");
   691      beta.append_list_value(list, "test3")
   692          .await
   693          .map_err(|e| format!("Could not run AppendListValue(): {}. Exiting!", e))?;
   694  
   695      println!("rust_async: Deleting value 'test2' from List...");
   696      beta.delete_list_value(list, "test2")
   697          .await
   698          .map_err(|e| format!("Could not run DeleteListValue(): {}. Exiting!", e))?;
   699  
   700      println!("rust_async: Getting List capacity...");
   701      let list_capacity = beta.get_list_capacity(list)
   702          .await
   703          .map_err(|e| format!("Could not run GetListCapacity(): {}. Exiting!", e))?;
   704      if list_capacity != 100 {
   705          return Err(format!("List capacity should be 100, but is {}", list_capacity));
   706      }
   707  
   708      println!("rust_async: Setting List capacity to 2...");
   709      beta.set_list_capacity(list, 2)
   710          .await
   711          .map_err(|e| format!("Could not run SetListCapacity(): {}. Exiting!", e))?;
   712  
   713      Ok(())
   714  }