diff --git a/tests/data/test1502 b/tests/data/test1502
index 3e3b3655273e97b9eb2980948671b85249338cbb..ac9e048a10289c42d8c4605004e3e1f5c83c854d 100644
--- a/tests/data/test1502
+++ b/tests/data/test1502
@@ -35,7 +35,7 @@ http
 lib1502
 </tool>
  <name>
-HTTP multi with CURLOPT_RESOLVE
+HTTP multi with CURLOPT_RESOLVE, cleanup sequence UA
  </name>
  <command>
 http://google.com:%HTTPPORT/1502 %HTTPPORT %HOSTIP
diff --git a/tests/libtest/Makefile.inc b/tests/libtest/Makefile.inc
index c773d2b7335bf629be4531a87388b076ea999fd0..e08176d577b76c4f8b76d73ebcc8017dd9490b0f 100644
--- a/tests/libtest/Makefile.inc
+++ b/tests/libtest/Makefile.inc
@@ -216,7 +216,8 @@ lib1500_LDADD = $(TESTUTIL_LIBS)
 lib1501_SOURCES = lib1501.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
 lib1501_LDADD = $(TESTUTIL_LIBS)
 
-lib1502_SOURCES = lib1502.c $(SUPPORTFILES)
+lib1502_SOURCES = lib1502.c $(SUPPORTFILES) $(TESTUTIL) $(WARNLESS)
+lib1502_LDADD = $(TESTUTIL_LIBS)
 
 libauthretry_SOURCES = libauthretry.c $(SUPPORTFILES)
 
diff --git a/tests/libtest/lib1502.c b/tests/libtest/lib1502.c
index 1ded5ab7ccd87e586600a595dbccf3405d856f79..c24006358bf8a43a62d12809c12ace1d29664ec3 100644
--- a/tests/libtest/lib1502.c
+++ b/tests/libtest/lib1502.c
@@ -20,8 +20,8 @@
  *
  ***************************************************************************/
 /*
- * Test case converted from bug report #3575448, identifying a memory leak in
- * the CURLOPT_RESOLVE handling with the multi interface.
+ * Test case 1502 converted from bug report #3575448, identifying a memory
+ * leak in the CURLOPT_RESOLVE handling with the multi interface.
  */
 
 #include "test.h"
@@ -30,107 +30,89 @@
 #include <limits.h>
 #endif
 
+#include "testutil.h"
+#include "warnless.h"
+#include "memdebug.h"
+
+#define TEST_HANG_TIMEOUT 60 * 1000
+
 int test(char *URL)
 {
-  CURL *ehandle;
-  CURLM *multi_handle;
-  char redirect[160];
-  CURLcode result = CURLE_NOT_BUILT_IN;
-  int still_running; /* keep number of running handles */
+  CURL* easy = NULL;
+  CURLM* multi = NULL;
+  int still_running;
+  int res = 0;
 
-  CURLMsg *msg; /* for picking up messages with the transfer status */
-  int msgs_left; /* how many messages are left */
+  char redirect[160];
 
   /* DNS cache injection */
   struct curl_slist *dns_cache_list;
 
   sprintf(redirect, "google.com:%s:%s", libtest_arg2, libtest_arg3);
 
-  fprintf(stderr, "Redirect: %s\n", redirect);
+  start_test_timing();
 
   dns_cache_list = curl_slist_append(NULL, redirect);
+  if(!dns_cache_list) {
+    fprintf(stderr, "curl_slist_append() failed\n");
+    return TEST_ERR_MAJOR_BAD;
+  }
+
+  res_global_init(CURL_GLOBAL_ALL);
+  if(res) {
+    curl_slist_free_all(dns_cache_list);
+    return res;
+  }
 
-  /* Allocate one CURL handle per transfer */
-  ehandle = curl_easy_init();
+  easy_init(easy);
 
-  /* set the options (I left out a few, you'll get the point anyway) */
-  curl_easy_setopt(ehandle, CURLOPT_URL, URL);
-  curl_easy_setopt(ehandle, CURLOPT_HEADER, 1L);
+  easy_setopt(easy, CURLOPT_URL, URL);
+  easy_setopt(easy, CURLOPT_HEADER, 1L);
+  easy_setopt(easy, CURLOPT_RESOLVE, dns_cache_list);
 
-  curl_easy_setopt(ehandle, CURLOPT_RESOLVE, dns_cache_list);
+  multi_init(multi);
 
-  /* init a multi stack */
-  multi_handle = curl_multi_init();
+  multi_add_handle(multi, easy);
 
-  /* add the individual transfers */
-  curl_multi_add_handle(multi_handle, ehandle);
+  multi_perform(multi, &still_running);
 
-  /* we start some action by calling perform right away */
-  curl_multi_perform(multi_handle, &still_running);
+  abort_on_test_timeout();
 
-  do {
+  while(still_running) {
     struct timeval timeout;
-    int rc; /* select() return code */
-
     fd_set fdread;
     fd_set fdwrite;
     fd_set fdexcep;
-    int maxfd = -1;
-
-    long curl_timeo = -1;
+    int maxfd = -99;
 
     FD_ZERO(&fdread);
     FD_ZERO(&fdwrite);
     FD_ZERO(&fdexcep);
-
-    /* set a suitable timeout to play around with */
     timeout.tv_sec = 1;
     timeout.tv_usec = 0;
 
-    curl_multi_timeout(multi_handle, &curl_timeo);
-    if(curl_timeo >= 0) {
-      int itimeout = (curl_timeo > (long)INT_MAX) ? INT_MAX : (int)curl_timeo;
-      timeout.tv_sec = itimeout / 1000;
-      if(timeout.tv_sec > 1)
-        timeout.tv_sec = 1;
-      else
-        timeout.tv_usec = (itimeout % 1000) * 1000;
-    }
-
-    /* get file descriptors from the transfers */
-    curl_multi_fdset(multi_handle, &fdread, &fdwrite, &fdexcep, &maxfd);
-
-    /* In a real-world program you OF COURSE check the return code of the
-       function calls.  On success, the value of maxfd is guaranteed to be
-       greater or equal than -1.  We call select(maxfd + 1, ...), specially in
-       case of (maxfd == -1), we call select(0, ...), which is basically equal
-       to sleep. */
-
-    rc = select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
-
-    switch(rc) {
-    case -1:
-      /* select error */
-      break;
-    case 0: /* timeout */
-    default: /* action */
-      curl_multi_perform(multi_handle, &still_running);
-      break;
-    }
-  } while(still_running);
-
-  /* See how the transfers went */
-  while ((msg = curl_multi_info_read(multi_handle, &msgs_left))) {
-    if (msg->msg == CURLMSG_DONE)
-      result = msg->data.result;
+    multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
+
+    /* At this point, maxfd is guaranteed to be greater or equal than -1. */
+
+    select_test(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
+
+    abort_on_test_timeout();
+
+    multi_perform(multi, &still_running);
+
+    abort_on_test_timeout();
   }
 
-  curl_multi_cleanup(multi_handle);
+test_cleanup:
+
+  /* undocumented cleanup sequence - type UA */
 
-  /* Free the CURL handles */
-  curl_easy_cleanup(ehandle);
+  curl_multi_cleanup(multi);
+  curl_easy_cleanup(easy);
+  curl_global_cleanup();
 
   curl_slist_free_all(dns_cache_list);
 
-  return (int)result;
+  return res;
 }