From 918539d8714842b574bf8503a8d144f6586f8b6b Mon Sep 17 00:00:00 2001
From: James Dinan <james.dinan@intel.com>
Date: Wed, 18 Dec 2019 21:17:28 -0500
Subject: [PATCH 1/2] Add 2d split unit test

Signed-off-by: James Dinan <james.dinan@intel.com>
---
 test/shmemx/Makefile.am            |   1 +
 test/shmemx/shmemx_team_split_2d.c | 100 +++++++++++++++++++++++++++++
 2 files changed, 101 insertions(+)
 create mode 100644 test/shmemx/shmemx_team_split_2d.c

diff --git a/test/shmemx/Makefile.am b/test/shmemx/Makefile.am
index 913c17af4..e92e97255 100644
--- a/test/shmemx/Makefile.am
+++ b/test/shmemx/Makefile.am
@@ -33,6 +33,7 @@ check_PROGRAMS += \
 	shmemx_test_all \
 	c11_test_shmemx_wait_until \
 	c11_test_shmemx_test \
+	shmemx_team_split_2d \
 	shmemx_team_translate_2 \
 	shmemx_team_reuse_teams \
 	shmemx_team_collect_active_set \
diff --git a/test/shmemx/shmemx_team_split_2d.c b/test/shmemx/shmemx_team_split_2d.c
new file mode 100644
index 000000000..027fade2e
--- /dev/null
+++ b/test/shmemx/shmemx_team_split_2d.c
@@ -0,0 +1,100 @@
+/*
+ *  Copyright (c) 2019 Intel Corporation. All rights reserved.
+ *  This software is available to you under the BSD license below:
+ *
+ *      Redistribution and use in source and binary forms, with or
+ *      without modification, are permitted provided that the following
+ *      conditions are met:
+ *
+ *      - Redistributions of source code must retain the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer.
+ *
+ *      - Redistributions in binary form must reproduce the above
+ *        copyright notice, this list of conditions and the following
+ *        disclaimer in the documentation and/or other materials
+ *        provided with the distribution.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include <stdio.h>
+#include <shmem.h>
+#include <shmemx.h>
+
+static int check_2d(shmemx_team_t team, int xdim) {
+    int me = shmemx_team_my_pe(team);
+
+    shmemx_team_t xteam, yteam;
+
+    int ret = shmemx_team_split_2d(team, xdim, NULL, 0, &xteam, NULL, 0, &yteam);
+    int errors = 0;
+
+    if (ret == 0) {
+        int npes_x = shmemx_team_n_pes(xteam);
+        int npes_y = shmemx_team_n_pes(yteam);
+
+        if (xteam == SHMEMX_TEAM_INVALID || yteam == SHMEMX_TEAM_INVALID) {
+            printf("%d: Error, received an invalid team\n", shmem_my_pe());
+            ++errors;
+        }
+
+        /* Try converting the PE ids from xteam and yteam to global indices and
+         * compare with the expected indices */
+        for (int i = 0; i < npes_x; i++) {
+            int pe_g       = shmemx_team_translate_pe(xteam, i, SHMEMX_TEAM_WORLD);
+            int expected_g = shmemx_team_translate_pe(team, me/xdim * xdim + i, SHMEMX_TEAM_WORLD);
+
+            if (pe_g != expected_g) {
+                printf("%d: xteam pe %d expected %d, got %d\n", me, i, pe_g, expected_g);
+                errors++;
+            }
+        }
+
+        for (int i = 0; i < npes_y; i++) {
+            int pe_g = shmemx_team_translate_pe(yteam, i, SHMEMX_TEAM_WORLD);
+            int expected_g = shmemx_team_translate_pe(team, me % xdim + i * xdim, SHMEMX_TEAM_WORLD);
+
+            if (pe_g != expected_g) {
+                printf("%d: yteam pe %d expected %d, got %d\n", me, i, pe_g, expected_g);
+                errors++;
+            }
+        }
+
+        shmemx_team_destroy(xteam);
+        shmemx_team_destroy(yteam);
+    }
+
+    return errors != 0;
+}
+
+int main(void) {
+    int errors = 0, npes, ret;
+    shmemx_team_t even_team;
+
+    shmem_init();
+
+    npes = shmem_n_pes();
+
+    errors += check_2d(SHMEMX_TEAM_WORLD, 1);
+    errors += check_2d(SHMEMX_TEAM_WORLD, 2);
+    errors += check_2d(SHMEMX_TEAM_WORLD, 3);
+
+    ret = shmemx_team_split_strided(SHMEMX_TEAM_WORLD, 0, 2, npes/2 + 1, NULL, 0, &even_team);
+
+    if (ret == 0) {
+        errors += check_2d(even_team, 1);
+        errors += check_2d(even_team, 2);
+        errors += check_2d(even_team, 3);
+    }
+
+    shmem_finalize();
+    return errors != 0;
+}

From a5c922d0d7adec0511798f7061b5e2736ee7756b Mon Sep 17 00:00:00 2001
From: James Dinan <james.dinan@gmail.com>
Date: Sat, 21 Dec 2019 11:32:37 -0500
Subject: [PATCH 2/2] Fix bugs in team split 2d unit test

Signed-off-by: James Dinan <james.dinan@gmail.com>
---
 test/shmemx/shmemx_team_split_2d.c | 68 ++++++++++++++++++++++--------
 1 file changed, 51 insertions(+), 17 deletions(-)

diff --git a/test/shmemx/shmemx_team_split_2d.c b/test/shmemx/shmemx_team_split_2d.c
index 027fade2e..a94a4356a 100644
--- a/test/shmemx/shmemx_team_split_2d.c
+++ b/test/shmemx/shmemx_team_split_2d.c
@@ -29,15 +29,18 @@
 #include <shmem.h>
 #include <shmemx.h>
 
-static int check_2d(shmemx_team_t team, int xdim) {
-    int me = shmemx_team_my_pe(team);
+static int check_2d(shmemx_team_t parent_team, int xdim) {
+    int me = shmemx_team_my_pe(parent_team);
 
-    shmemx_team_t xteam, yteam;
+    shmemx_team_t xteam = SHMEMX_TEAM_INVALID;
+    shmemx_team_t yteam = SHMEMX_TEAM_INVALID;
 
-    int ret = shmemx_team_split_2d(team, xdim, NULL, 0, &xteam, NULL, 0, &yteam);
+    int ret = shmemx_team_split_2d(parent_team, xdim, NULL, 0, &xteam, NULL, 0, &yteam);
     int errors = 0;
 
     if (ret == 0) {
+        int me_x = shmemx_team_my_pe(xteam);
+        int me_y = shmemx_team_my_pe(yteam);
         int npes_x = shmemx_team_n_pes(xteam);
         int npes_y = shmemx_team_n_pes(yteam);
 
@@ -46,53 +49,84 @@ static int check_2d(shmemx_team_t team, int xdim) {
             ++errors;
         }
 
-        /* Try converting the PE ids from xteam and yteam to global indices and
-         * compare with the expected indices */
+        /* Try converting the PE ids from xteam and yteam to parent and global
+         * PE indices and compare with the expected indices */
         for (int i = 0; i < npes_x; i++) {
-            int pe_g       = shmemx_team_translate_pe(xteam, i, SHMEMX_TEAM_WORLD);
-            int expected_g = shmemx_team_translate_pe(team, me/xdim * xdim + i, SHMEMX_TEAM_WORLD);
+            int expected_parent = me_y * xdim + i; /* row (fixed) + column */
+            int pe_parent       = shmemx_team_translate_pe(xteam, i, parent_team);
+            int pe_world        = shmemx_team_translate_pe(xteam, i, SHMEMX_TEAM_WORLD);
+            int expected_world  = shmemx_team_translate_pe(parent_team, expected_parent, SHMEMX_TEAM_WORLD);
+
+            if (expected_parent != pe_parent) {
+                printf("%d: xteam[%d] expected parent PE id %d, got %d\n",
+                        me, i, expected_parent, pe_parent);
+                errors++;
+            }
 
-            if (pe_g != expected_g) {
-                printf("%d: xteam pe %d expected %d, got %d\n", me, i, pe_g, expected_g);
+            if (expected_world != pe_world) {
+                printf("%d: xteam[%d] expected world PE id %d, got %d\n",
+                        me, i, expected_world, pe_world);
                 errors++;
             }
         }
 
         for (int i = 0; i < npes_y; i++) {
-            int pe_g = shmemx_team_translate_pe(yteam, i, SHMEMX_TEAM_WORLD);
-            int expected_g = shmemx_team_translate_pe(team, me % xdim + i * xdim, SHMEMX_TEAM_WORLD);
+            int expected_parent = i * xdim + me_x; /* row + column (fixed) */
+            int pe_parent       = shmemx_team_translate_pe(yteam, i, parent_team);
+            int pe_world        = shmemx_team_translate_pe(yteam, i, SHMEMX_TEAM_WORLD);
+            int expected_world  = shmemx_team_translate_pe(parent_team, expected_parent, SHMEMX_TEAM_WORLD);
+
+            if (expected_parent != pe_parent) {
+                printf("%d: yteam[%d] expected parent PE id %d, got %d\n",
+                        me, i, expected_parent, pe_parent);
+                errors++;
+            }
 
-            if (pe_g != expected_g) {
-                printf("%d: yteam pe %d expected %d, got %d\n", me, i, pe_g, expected_g);
+            if (expected_world != pe_world) {
+                printf("%d: yteam[%d] expected world PE id %d, got %d\n",
+                        me, i, expected_world, pe_world);
                 errors++;
             }
         }
+    }
+    else {
+        printf("%d: 2d split failed\n", shmem_my_pe());
+    }
 
+    if (xteam != SHMEMX_TEAM_INVALID)
         shmemx_team_destroy(xteam);
+    if (yteam != SHMEMX_TEAM_INVALID)
         shmemx_team_destroy(yteam);
-    }
 
     return errors != 0;
 }
 
 int main(void) {
-    int errors = 0, npes, ret;
+    int errors = 0, me, npes, ret;
     shmemx_team_t even_team;
 
     shmem_init();
 
+    me   = shmem_my_pe();
     npes = shmem_n_pes();
 
+    if (me == 0) printf("Performing 2d split test on SHMEM_TEAM_WORLD\n");
+
     errors += check_2d(SHMEMX_TEAM_WORLD, 1);
     errors += check_2d(SHMEMX_TEAM_WORLD, 2);
     errors += check_2d(SHMEMX_TEAM_WORLD, 3);
 
-    ret = shmemx_team_split_strided(SHMEMX_TEAM_WORLD, 0, 2, npes/2 + 1, NULL, 0, &even_team);
+    ret = shmemx_team_split_strided(SHMEMX_TEAM_WORLD, 0, 2, (npes-1)/2 + 1,
+                                    NULL, 0, &even_team);
 
     if (ret == 0) {
+        if (me == 0) printf("Performing 2d split test on even team\n");
+
         errors += check_2d(even_team, 1);
         errors += check_2d(even_team, 2);
         errors += check_2d(even_team, 3);
+    } else {
+        if (me == 0) printf("Unable to create even team\n");
     }
 
     shmem_finalize();