View | Details | Raw Unified | Return to ticket 13749
Collapse All | Expand All

(-)a/src/common/hostlist.c (-53 / +357 lines)
Lines 151-157 typedef struct { Link Here
151
	char *prefix;           /* hostname prefix                      */
151
	char *prefix;           /* hostname prefix                      */
152
	unsigned long num;      /* numeric suffix                       */
152
	unsigned long num;      /* numeric suffix                       */
153
153
154
	/* string representation of numeric suffix
154
	/* string representation of numeric suffix, and trailing chars
155
	 * points into `hostname'                                       */
155
	 * points into `hostname'                                       */
156
	char *suffix;
156
	char *suffix;
157
} hostname_t;
157
} hostname_t;
Lines 159-164 typedef struct { Link Here
159
/* hostrange type: A single prefix with `hi' and `lo' numeric suffix values */
159
/* hostrange type: A single prefix with `hi' and `lo' numeric suffix values */
160
typedef struct {
160
typedef struct {
161
	char *prefix;        /* alphanumeric prefix: */
161
	char *prefix;        /* alphanumeric prefix: */
162
	char *suffix;
162
163
163
	/* beginning (lo) and end (hi) of suffix range */
164
	/* beginning (lo) and end (hi) of suffix range */
164
	unsigned long lo, hi;
165
	unsigned long lo, hi;
Lines 283-301 static int _width_equiv(unsigned long, int *, unsigned long, int *); Link Here
283
284
284
static int           host_prefix_end(const char *, int dims);
285
static int           host_prefix_end(const char *, int dims);
285
static hostname_t *hostname_create(const char *);
286
static hostname_t *hostname_create(const char *);
287
static hostname_t *hostname_copy(const hostname_t *);
286
static void hostname_destroy(hostname_t *);
288
static void hostname_destroy(hostname_t *);
287
static int hostname_suffix_is_valid(hostname_t *);
289
static int hostname_suffix_is_valid(hostname_t *);
288
static int hostname_suffix_width(hostname_t *);
290
static int hostname_suffix_width(hostname_t *, int);
291
static char *hostname_suffix_extra(hostname_t *, int);
289
292
290
static hostrange_t *hostrange_new(void);
293
static hostrange_t *hostrange_new(void);
291
static hostrange_t *hostrange_create_single(const char *);
294
static hostrange_t *hostrange_create_single(const char *);
292
static hostrange_t *hostrange_create(char *, unsigned long, unsigned long, int);
295
static hostrange_t *hostrange_create(char *, unsigned long, unsigned long, int, char *);
293
static unsigned long hostrange_count(hostrange_t *);
296
static unsigned long hostrange_count(hostrange_t *);
294
static hostrange_t *hostrange_copy(hostrange_t *);
297
static hostrange_t *hostrange_copy(hostrange_t *);
295
static void hostrange_destroy(hostrange_t *);
298
static void hostrange_destroy(hostrange_t *);
296
static hostrange_t *hostrange_delete_host(hostrange_t *, unsigned long);
299
static hostrange_t *hostrange_delete_host(hostrange_t *, unsigned long);
297
static int hostrange_cmp(hostrange_t *, hostrange_t *);
300
static int hostrange_cmp(hostrange_t *, hostrange_t *);
298
static int hostrange_prefix_cmp(hostrange_t *, hostrange_t *);
301
static int hostrange_prefix_cmp(hostrange_t *, hostrange_t *);
302
static int hostrange_prefix_suffix_cmp(hostrange_t *, hostrange_t *);
299
static int hostrange_within_range(hostrange_t *, hostrange_t *);
303
static int hostrange_within_range(hostrange_t *, hostrange_t *);
300
static int hostrange_width_combine(hostrange_t *, hostrange_t *);
304
static int hostrange_width_combine(hostrange_t *, hostrange_t *);
301
static int hostrange_empty(hostrange_t *);
305
static int hostrange_empty(hostrange_t *);
Lines 314-320 static int hostlist_resize(hostlist_t, size_t); Link Here
314
static int         hostlist_expand(hostlist_t);
318
static int         hostlist_expand(hostlist_t);
315
static int hostlist_push_range(hostlist_t, hostrange_t *);
319
static int hostlist_push_range(hostlist_t, hostrange_t *);
316
static int         hostlist_push_hr(hostlist_t, char *, unsigned long,
320
static int         hostlist_push_hr(hostlist_t, char *, unsigned long,
317
                                    unsigned long, int);
321
		unsigned long, int, char *);
318
static int hostlist_insert_range(hostlist_t, hostrange_t *, int);
322
static int hostlist_insert_range(hostlist_t, hostrange_t *, int);
319
static void        hostlist_delete_range(hostlist_t, int n);
323
static void        hostlist_delete_range(hostlist_t, int n);
320
static void        hostlist_coalesce(hostlist_t hl);
324
static void        hostlist_coalesce(hostlist_t hl);
Lines 489-494 static hostname_t *hostname_create_dims(const char *hostname, int dims) Link Here
489
	char *p;
493
	char *p;
490
	int idx = 0;
494
	int idx = 0;
491
	int hostlist_base;
495
	int hostlist_base;
496
	int suffix_len;
492
497
493
	xassert(hostname);
498
	xassert(hostname);
494
499
Lines 518-530 static hostname_t *hostname_create_dims(const char *hostname, int dims) Link Here
518
	}
523
	}
519
524
520
	hn->suffix = hn->hostname + idx + 1;
525
	hn->suffix = hn->hostname + idx + 1;
526
	suffix_len = hostname_suffix_width(hn, dims);
521
527
522
	if ((dims > 1) && (strlen(hn->suffix) != dims))
528
	if ((dims > 1) && (suffix_len != dims))
523
		hostlist_base = 10;
529
		hostlist_base = 10;
524
530
525
	hn->num = strtoul(hn->suffix, &p, hostlist_base);
531
	hn->num = strtoul(hn->suffix, &p, hostlist_base);
526
532
527
	if (*p == '\0') {
533
	if (p - hn->suffix == suffix_len) {
528
		if (!(hn->prefix = malloc((idx + 2)))) {
534
		if (!(hn->prefix = malloc((idx + 2)))) {
529
			hostname_destroy(hn);
535
			hostname_destroy(hn);
530
			out_of_memory("hostname prefix create");
536
			out_of_memory("hostname prefix create");
Lines 551-556 static hostname_t *hostname_create(const char *hostname) Link Here
551
	return hostname_create_dims(hostname, dims);
557
	return hostname_create_dims(hostname, dims);
552
}
558
}
553
559
560
/*
561
 * make a copy of a hostname object
562
 */
563
static hostname_t *hostname_copy(const hostname_t *hn)
564
{
565
	hostname_t *ret;
566
567
	if (hn == NULL)
568
		return NULL;
569
570
	if ((ret = malloc(sizeof(*ret))) == NULL)
571
		out_of_memory("hostname copy");
572
573
	ret->hostname = strdup(hn->hostname);
574
	ret->prefix = strdup(hn->prefix);
575
	ret->suffix = hn->suffix ? ret->hostname + (hn->suffix - hn->hostname) : NULL;
576
	ret->num = hn->num;
577
578
	if (!ret->hostname || !ret->prefix) {
579
		hostname_destroy(ret);
580
		ret = NULL;
581
		out_of_memory("hostname copy");
582
	}
583
584
	return ret;
585
}
586
554
/* free a hostname object
587
/* free a hostname object
555
 */
588
 */
556
static void hostname_destroy(hostname_t *hn)
589
static void hostname_destroy(hostname_t *hn)
Lines 576-594 static int hostname_suffix_is_valid(hostname_t *hn) Link Here
576
609
577
/* return the width (in characters) of the numeric part of the hostname
610
/* return the width (in characters) of the numeric part of the hostname
578
 */
611
 */
579
static int hostname_suffix_width(hostname_t *hn)
612
static int hostname_suffix_width(hostname_t *hn, int dims)
580
{
613
{
614
	int idx = 0;
581
	if (!hn)
615
	if (!hn)
582
		return -1;
616
		return -1;
583
	xassert(hn->suffix);
617
	xassert(hn->suffix);
584
	return (int) strlen(hn->suffix);
618
619
	if (dims > 1)
620
		return (int) strlen(hn->suffix);
621
	while (hn->suffix[idx] != '\0' && isdigit(hn->suffix[idx]))
622
		idx++;
623
	return idx;
585
}
624
}
586
625
626
/* return a pointer to extra data after the numeric suffix, or NULL if none
627
*/
628
static char *hostname_suffix_extra(hostname_t *hn, int dims)
629
{
630
	int width = hostname_suffix_width(hn, dims);
631
	if (width > 0 && strlen(hn->suffix) > width)
632
		return hn->suffix + width;
633
	return NULL;
634
}
587
635
588
/* ----[ hostrange_t functions ]---- */
636
/* ----[ hostrange_t functions ]---- */
589
637
590
/* allocate a new hostrange object
638
/* allocate a new hostrange object
591
 */
639
*/
592
static hostrange_t *hostrange_new(void)
640
static hostrange_t *hostrange_new(void)
593
{
641
{
594
	hostrange_t *new = malloc(sizeof(*new));
642
	hostrange_t *new = malloc(sizeof(*new));
Lines 616-621 static hostrange_t *hostrange_create_single(const char *prefix) Link Here
616
	new->lo = 0L;
664
	new->lo = 0L;
617
	new->hi = 0L;
665
	new->hi = 0L;
618
	new->width = 0;
666
	new->width = 0;
667
	new->suffix = NULL;
619
668
620
	return new;
669
	return new;
621
670
Lines 629-635 error1: Link Here
629
/* Create a hostrange object with a prefix, hi, lo, and format width
678
/* Create a hostrange object with a prefix, hi, lo, and format width
630
 */
679
 */
631
static hostrange_t *hostrange_create(char *prefix, unsigned long lo,
680
static hostrange_t *hostrange_create(char *prefix, unsigned long lo,
632
				     unsigned long hi, int width)
681
				     unsigned long hi, int width, char *suffix)
633
{
682
{
634
	hostrange_t *new;
683
	hostrange_t *new;
635
684
Lines 641-646 static hostrange_t *hostrange_create(char *prefix, unsigned long lo, Link Here
641
	if ((new->prefix = strdup(prefix)) == NULL)
690
	if ((new->prefix = strdup(prefix)) == NULL)
642
		goto error2;
691
		goto error2;
643
692
693
	new->suffix = NULL;
694
	if (suffix && ((new->suffix = strdup(suffix)) == NULL))
695
		goto error3;
696
644
	new->lo = lo;
697
	new->lo = lo;
645
	new->hi = hi;
698
	new->hi = hi;
646
	new->width = width;
699
	new->width = width;
Lines 649-654 static hostrange_t *hostrange_create(char *prefix, unsigned long lo, Link Here
649
702
650
	return new;
703
	return new;
651
704
705
error3:
706
	free(new->prefix);
652
error2:
707
error2:
653
	free(new);
708
	free(new);
654
error1:
709
error1:
Lines 675-683 static hostrange_t *hostrange_copy(hostrange_t *hr) Link Here
675
730
676
	if (hr->singlehost)
731
	if (hr->singlehost)
677
		return hostrange_create_single(hr->prefix);
732
		return hostrange_create_single(hr->prefix);
678
	else
733
	return hostrange_create(hr->prefix, hr->lo, hr->hi, hr->width, hr->suffix);
679
		return hostrange_create(hr->prefix, hr->lo, hr->hi,
680
					hr->width);
681
}
734
}
682
735
683
736
Lines 689-694 static void hostrange_destroy(hostrange_t *hr) Link Here
689
		return;
742
		return;
690
	if (hr->prefix)
743
	if (hr->prefix)
691
		free(hr->prefix);
744
		free(hr->prefix);
745
	if (hr->suffix)
746
		free(hr->suffix);
692
	free(hr);
747
	free(hr);
693
}
748
}
694
749
Lines 727-734 extern int hostlist_cmp_first(hostlist_t hl1, hostlist_t hl2) Link Here
727
/* hostrange_cmp() is used to sort hostrange objects. It will
782
/* hostrange_cmp() is used to sort hostrange objects. It will
728
 * sort based on the following (in order):
783
 * sort based on the following (in order):
729
 *  o result of xstrcmp on prefixes
784
 *  o result of xstrcmp on prefixes
785
 *  o result of xstrcmp on suffixes
730
 *  o if widths are compatible, then:
786
 *  o if widths are compatible, then:
731
 *       sort based on lowest suffix in range
787
 *       sort based on lowest number in range
732
 *    else
788
 *    else
733
 *       sort based on width                     */
789
 *       sort based on width                     */
734
static int hostrange_cmp(hostrange_t *h1, hostrange_t *h2)
790
static int hostrange_cmp(hostrange_t *h1, hostrange_t *h2)
Lines 737-745 static int hostrange_cmp(hostrange_t *h1, hostrange_t *h2) Link Here
737
793
738
	xassert(h1 && h2);
794
	xassert(h1 && h2);
739
795
740
	if ((retval = hostrange_prefix_cmp(h1, h2)) == 0)
796
	if ((retval = hostrange_prefix_cmp(h1, h2)) == 0) {
741
		retval = hostrange_width_combine(h1, h2) ?
797
		if (retval == 0) {
742
			h1->lo - h2->lo : h1->width - h2->width;
798
			if (h1->suffix && !h2->suffix)
799
				retval = 1;
800
			else if (!h1->suffix && h2->suffix)
801
				retval = -1;
802
			else if (h1->suffix && h2->suffix)
803
				retval = strnatcmp(h1->suffix, h2->suffix);
804
		}
805
		if (retval == 0)
806
			retval = hostrange_width_combine(h1, h2) ?
807
				h1->lo - h2->lo : h1->width - h2->width;
808
	}
743
809
744
	return retval;
810
	return retval;
745
}
811
}
Lines 764-769 static int hostrange_prefix_cmp(hostrange_t *h1, hostrange_t *h2) Link Here
764
	return retval == 0 ? h2->singlehost - h1->singlehost : retval;
830
	return retval == 0 ? h2->singlehost - h1->singlehost : retval;
765
}
831
}
766
832
833
/* compare the prefixes and suffixes of two hostrange objects
834
 * returns:
835
 *    0      if both are the same
836
 *    non-0  if different
837
 *
838
 * (not lexicographic, do not use in sorting) */
839
static int hostrange_prefix_suffix_cmp(hostrange_t *h1, hostrange_t *h2)
840
{
841
	if (hostrange_prefix_cmp(h1, h2))
842
		return 1;
843
	if (h1->suffix == NULL && h2->suffix == NULL)
844
		return 0;
845
	if (h1->suffix != NULL && h2->suffix != NULL)
846
		return strnatcmp(h1->suffix, h2->suffix);
847
	return 1;
848
}
849
767
/* returns true if h1 and h2 would be included in the same bracketed hostlist.
850
/* returns true if h1 and h2 would be included in the same bracketed hostlist.
768
 * h1 and h2 will be in the same bracketed list iff:
851
 * h1 and h2 will be in the same bracketed list iff:
769
 *
852
 *
Lines 775-781 static int hostrange_prefix_cmp(hostrange_t *h1, hostrange_t *h2) Link Here
775
 */
858
 */
776
static int hostrange_within_range(hostrange_t *h1, hostrange_t *h2)
859
static int hostrange_within_range(hostrange_t *h1, hostrange_t *h2)
777
{
860
{
778
	if (hostrange_prefix_cmp(h1, h2) == 0)
861
	if (hostrange_prefix_suffix_cmp(h1, h2) == 0)
779
		return h1->singlehost || h2->singlehost ? 0 : 1;
862
		return h1->singlehost || h2->singlehost ? 0 : 1;
780
	else
863
	else
781
		return 0;
864
		return 0;
Lines 803-808 static int hostrange_empty(hostrange_t *hr) Link Here
803
	return ((hr->hi < hr->lo) || (hr->hi == (unsigned long) -1));
886
	return ((hr->hi < hr->lo) || (hr->hi == (unsigned long) -1));
804
}
887
}
805
888
889
/* Convert existing single hostrange with no suffix into numeric range with a suffix
890
 */
891
static int hostrange_convert_suffix(hostrange_t *hr, unsigned long n, unsigned long width, unsigned long suffix_idx)
892
{
893
	size_t prefix_len;
894
	xassert(hr && hr->prefix);
895
896
	prefix_len = strlen(hr->prefix);
897
898
	if (hostrange_count(hr) != 1 || hr->suffix || suffix_idx >= prefix_len || width == 0)
899
		return 0;
900
901
	if (!(hr->suffix = malloc(strlen(hr->prefix) - suffix_idx + hr->width + 1)))
902
		return 0;
903
904
	/* copy previous numeric suffix in (if any) */
905
	if (hr->width)
906
		sprintf(hr->suffix, "%s%0*lu", hr->prefix + suffix_idx, hr->width, hr->lo);
907
	else
908
		strcpy(hr->suffix, hr->prefix + suffix_idx);
909
910
	/* truncate the prefix */
911
	hr->prefix[suffix_idx - width] = 0;
912
	/* reset numeric settings */
913
	hr->width = width;
914
	hr->lo = n;
915
	hr->hi = n;
916
	hr->singlehost = 0;
917
	return 1;
918
}
919
920
921
/* Attempt to extract a number of the given width from a string,
922
 * return 0 on success, and set *res to extracted number,
923
 * 1 on failure
924
 */
925
static int
926
_extract_num_width(char *buf, size_t width, unsigned long *res)
927
{
928
	char *endptr;
929
	unsigned long x = strtoul(buf, &endptr, 10);
930
	if (x == ULONG_MAX || endptr - buf != width)
931
		return 1;
932
	*res = x;
933
	return 0;
934
}
935
936
/* Compare left suffix == right suffix + number
937
 * 0 on success, 1 on failure, like strcmp */
938
	static int
939
_compare_str_num(char *left, char *right, unsigned long idx, unsigned long width)
940
{
941
	if (strncmp(left, right, strlen(right)))
942
		return 1;
943
	if (width) {
944
		unsigned long num;
945
		if (_extract_num_width(left+ strlen(right), width, &num) ||
946
				num != idx)
947
			return 1;
948
	}
949
	return 0;
950
}
951
952
/* Compare two hostranges to see if they have a numeric part in the middle
953
 * of the prefix and can be combined into one range.
954
 * If they can, return hr1 if they can be combined into it, otherwise
955
 * try to fix up both to have a common suffix and return NULL
956
 */
957
static hostrange_t *
958
hostrange_combine_suffix(hostrange_t *hr1, hostrange_t *hr2)
959
{
960
	int i;
961
962
	xassert(hr1 && hr2);
963
	/* First test, to see if we can combine two single host ranges into a range
964
	 * with a numerical part in the middle.
965
	 * Can only combine if the current numeric suffix is the same, and the
966
	 * length of the prefixes is the same, and we don't have a prefix/suffix split already,
967
	 * and any numeric suffix is the same */
968
	if ((hr1->singlehost != hr2->singlehost) ||
969
			(strlen(hr1->prefix) != strlen(hr2->prefix)) ||
970
			hr1->suffix || hr2->suffix ||
971
			hr1->lo != hr2->lo ||
972
			hr1->hi != hr2->hi ||
973
			hostrange_count(hr1) != 1 ||
974
			hr1->width != hr2->width) {
975
		/* Another possibility - if this is adding a single host to an existing range,
976
		 * and the numeric suffix of hr2 would match the string suffix of hr1 */
977
		if (!hr1->singlehost && hr1->suffix &&
978
				hostrange_count(hr2) == 1 && hr2->suffix == NULL) {
979
			size_t hr1_prefix_len = strlen(hr1->prefix);
980
			size_t hr2_prefix_len = strlen(hr2->prefix);
981
			unsigned long hr2_idx;
982
			/* Total length should match */
983
			if (hr1_prefix_len + hr1->width + strlen(hr1->suffix) !=
984
					hr2_prefix_len + hr2->width)
985
				return NULL;
986
			/* We now may have two ranges of the form:
987
			 *
988
			 *         /-- hr1 prefix
989
			 *         |   /-- hr1 lo
990
			 *         |   |   /--- hr1 suffix
991
			 *         foo-1234-111
992
			 *         foo-1235-111
993
			 *         |        ^ hr2 lo
994
			 *         \-- hr2 prefix
995
			 *
996
			 * Walk along hr2 and compare to hr1
997
			 */
998
			/* Compare prefix */
999
			if (strncmp(hr1->prefix, hr2->prefix, hr1_prefix_len))
1000
				return NULL;
1001
			/* Extract numeric portion */
1002
			if (_extract_num_width(hr2->prefix + hr1_prefix_len, hr1->width, &hr2_idx))
1003
				return NULL;
1004
			/* compare the suffix */
1005
			if (hr1_prefix_len + hr1->width >= hr2_prefix_len ||
1006
					_compare_str_num(hr1->suffix, hr2->prefix + hr1_prefix_len + hr1->width, hr2->lo, hr2->width))
1007
				return NULL;
1008
			/* If the numbers are not consecutive, we still want to convert the second entry to
1009
			 * prefix/suffix form so that printouts can combine them */
1010
			if (hr2_idx != hr1->hi + 1) {
1011
				hostrange_convert_suffix(hr2, hr2_idx, hr1->width, hr1_prefix_len + hr1->width);
1012
				return NULL;
1013
			}
1014
			/* At this point everything matches, expand the range of hr1 */
1015
			hr1->hi++;
1016
			return hr1;
1017
		}
1018
		return NULL;
1019
	}
1020
1021
	/* Here we have two single host ranges with a numeric suffix, attempt to find
1022
	 * a common ascending range of numbers between the two */
1023
	for (i = 0; i < strlen(hr1->prefix); i++) {
1024
		if (isdigit(hr1->prefix[i])) {
1025
			unsigned long p1, p2;
1026
			char *endp1, *endp2;
1027
			p1 = strtoul(hr1->prefix + i, &endp1, 10);
1028
			p2 = strtoul(hr2->prefix + i, &endp2, 10);
1029
			/* widths of numeric field should match, but
1030
			 * the numbers themselves should be consecutive */
1031
			if ((endp1 - hr1->prefix) == (endp2 - hr2->prefix) && (p1 != p2)) {
1032
				int prefix_len = i;
1033
1034
				/* the rest of the prefix should match as well */
1035
				i = endp1 - hr1->prefix;
1036
				if (strcmp(hr1->prefix + i, hr2->prefix + i) != 0) {
1037
					return NULL;
1038
				}
1039
				/* Ok, we have a match, convert them to the correct suffix
1040
				 * so that they can be coalesced above */
1041
				hostrange_convert_suffix(hr1, p1, i - prefix_len, i);
1042
				/* if they are consecutive, extend the first range,
1043
				 * otherwise leave them distinct so they can be grouped in printout */
1044
				if (p2 - p1 == 1) {
1045
					hr1->hi = p2;
1046
					return hr1;
1047
				}
1048
				hostrange_convert_suffix(hr2, p2, i - prefix_len, i);
1049
				return NULL;
1050
			}
1051
		}
1052
	}
1053
	return NULL;
1054
}
1055
1056
806
/* return the string representation of the last host in hostrange hr
1057
/* return the string representation of the last host in hostrange hr
807
 * and remove that host from the range (i.e. decrement hi if possible)
1058
 * and remove that host from the range (i.e. decrement hi if possible)
808
 *
1059
 *
Lines 823-828 static char *hostrange_pop(hostrange_t *hr) Link Here
823
			out_of_memory("hostrange pop");
1074
			out_of_memory("hostrange pop");
824
	} else if (hostrange_count(hr) > 0) {
1075
	} else if (hostrange_count(hr) > 0) {
825
		size = strlen(hr->prefix) + hr->width + 16;
1076
		size = strlen(hr->prefix) + hr->width + 16;
1077
		if (hr->suffix) size += strlen(hr->suffix);
826
		if (!(host = malloc(size)))
1078
		if (!(host = malloc(size)))
827
			out_of_memory("hostrange pop");
1079
			out_of_memory("hostrange pop");
828
		if ((dims > 1) && (hr->width == dims)) {
1080
		if ((dims > 1) && (hr->width == dims)) {
Lines 832-837 static char *hostrange_pop(hostrange_t *hr) Link Here
832
1084
833
			hostlist_parse_int_to_array(hr->hi, coord, dims, 0);
1085
			hostlist_parse_int_to_array(hr->hi, coord, dims, 0);
834
1086
1087
			xassert(!hr->suffix);
835
			len = snprintf(host, size, "%s", hr->prefix);
1088
			len = snprintf(host, size, "%s", hr->prefix);
836
			if (len >= 0 && len + dims < size) {
1089
			if (len >= 0 && len + dims < size) {
837
				while (i2 < dims)
1090
				while (i2 < dims)
Lines 840-847 static char *hostrange_pop(hostrange_t *hr) Link Here
840
			}
1093
			}
841
			hr->hi--;
1094
			hr->hi--;
842
		} else {
1095
		} else {
843
			snprintf(host, size, "%s%0*lu", hr->prefix,
1096
			snprintf(host, size, "%s%0*lu%s", hr->prefix,
844
				 hr->width, hr->hi--);
1097
				 hr->width, hr->hi--, hr->suffix ? hr->suffix : "");
845
		}
1098
		}
846
	}
1099
	}
847
1100
Lines 865-870 static char *hostrange_shift(hostrange_t *hr, int dims) Link Here
865
			out_of_memory("hostrange shift");
1118
			out_of_memory("hostrange shift");
866
	} else if (hostrange_count(hr) > 0) {
1119
	} else if (hostrange_count(hr) > 0) {
867
		size = strlen(hr->prefix) + hr->width + 16;
1120
		size = strlen(hr->prefix) + hr->width + 16;
1121
		if (hr->suffix) size += strlen(hr->suffix);
868
		if (!(host = malloc(size)))
1122
		if (!(host = malloc(size)))
869
			out_of_memory("hostrange shift");
1123
			out_of_memory("hostrange shift");
870
		if ((dims > 1) && (hr->width == dims)) {
1124
		if ((dims > 1) && (hr->width == dims)) {
Lines 874-879 static char *hostrange_shift(hostrange_t *hr, int dims) Link Here
874
1128
875
			hostlist_parse_int_to_array(hr->lo, coord, dims, 0);
1129
			hostlist_parse_int_to_array(hr->lo, coord, dims, 0);
876
1130
1131
			xassert(!hr->suffix);
877
			len = snprintf(host, size, "%s", hr->prefix);
1132
			len = snprintf(host, size, "%s", hr->prefix);
878
			if (len >= 0 && len + dims < size) {
1133
			if (len >= 0 && len + dims < size) {
879
				while (i2 < dims)
1134
				while (i2 < dims)
Lines 882-889 static char *hostrange_shift(hostrange_t *hr, int dims) Link Here
882
			}
1137
			}
883
			hr->lo++;
1138
			hr->lo++;
884
		} else {
1139
		} else {
885
			snprintf(host, size, "%s%0*lu", hr->prefix,
1140
			snprintf(host, size, "%s%0*lu%s", hr->prefix,
886
				 hr->width, hr->lo++);
1141
				 hr->width, hr->lo++, hr->suffix ? hr->suffix : "");
887
		}
1142
		}
888
	}
1143
	}
889
1144
Lines 911-917 static int hostrange_join(hostrange_t *h1, hostrange_t *h2) Link Here
911
	xassert(h1 && h2);
1166
	xassert(h1 && h2);
912
	xassert(hostrange_cmp(h1, h2) <= 0);
1167
	xassert(hostrange_cmp(h1, h2) <= 0);
913
1168
914
	if (hostrange_prefix_cmp(h1, h2) == 0 &&
1169
	if (hostrange_prefix_suffix_cmp(h1, h2) == 0 &&
915
	    hostrange_width_combine(h1, h2)) {
1170
	    hostrange_width_combine(h1, h2)) {
916
1171
917
		if (h1->singlehost && h2->singlehost) {    /* matching singlets  */
1172
		if (h1->singlehost && h2->singlehost) {    /* matching singlets  */
Lines 949-955 static hostrange_t *hostrange_intersect(hostrange_t *h1, hostrange_t *h2) Link Here
949
	xassert(hostrange_cmp(h1, h2) <= 0);
1204
	xassert(hostrange_cmp(h1, h2) <= 0);
950
1205
951
	if ((h1->hi > h2->lo)
1206
	if ((h1->hi > h2->lo)
952
	    && (hostrange_prefix_cmp(h1, h2) == 0)
1207
	    && (hostrange_prefix_suffix_cmp(h1, h2) == 0)
953
	    && (hostrange_width_combine(h1, h2))) {
1208
	    && (hostrange_width_combine(h1, h2))) {
954
1209
955
		if (!(new = hostrange_copy(h1)))
1210
		if (!(new = hostrange_copy(h1)))
Lines 964-971 static hostrange_t *hostrange_intersect(hostrange_t *h1, hostrange_t *h2) Link Here
964
/* return 1 if hostname hn is within the hostrange hr
1219
/* return 1 if hostname hn is within the hostrange hr
965
 *        0 if not.
1220
 *        0 if not.
966
 */
1221
 */
967
static int hostrange_hn_within(hostrange_t *hr, hostname_t *hn, int dims)
1222
static int hostrange_hn_within(hostrange_t *hr, hostname_t *hn_orig, int dims)
968
{
1223
{
1224
    hostname_t *hn = hn_orig;
1225
    int ret = 0;
1226
969
	if (hr->singlehost) {
1227
	if (hr->singlehost) {
970
		/*
1228
		/*
971
		 *  If the current hostrange [hr] is a `singlehost' (no valid
1229
		 *  If the current hostrange [hr] is a `singlehost' (no valid
Lines 1024-1041 static int hostrange_hn_within(hostrange_t *hr, hostname_t *hn, int dims) Link Here
1024
		if (len1 == len2)
1282
		if (len1 == len2)
1025
			return 0;
1283
			return 0;
1026
1284
1285
		/* Make a copy of the hostname to mess with */
1286
		hn = hostname_copy(hn_orig);
1287
1288
		if (!hn)
1289
			return 0;
1290
1027
		ldiff = len1 - len2;
1291
		ldiff = len1 - len2;
1028
1292
1029
		if (ldiff > 0 && (strlen(hn->suffix) >= ldiff)) {
1293
		if (ldiff > 0 && (hostname_suffix_width(hn, dims) >= ldiff)) {
1030
			/* Tack on ldiff of the hostname's suffix to
1294
			/* Tack on ldiff of the hostname's suffix to
1031
			 * that of it's prefix */
1295
			 * that of it's prefix */
1032
			hn->prefix = realloc(hn->prefix, len2+ldiff+1);
1296
			hn->prefix = realloc(hn->prefix, len2+ldiff+1);
1297
			if (!hn->prefix) {
1298
				goto free_cpy;
1299
			}
1033
			strncat(hn->prefix, hn->suffix, ldiff);
1300
			strncat(hn->prefix, hn->suffix, ldiff);
1034
		} else if (ldiff < 0) {
1301
		} else if (ldiff < 0) {
1035
			/* strip off the ldiff here */
1302
			/* strip off the ldiff here */
1036
			hn->prefix[len2+ldiff] = '\0';
1303
			hn->prefix[len2+ldiff] = '\0';
1037
		} else
1304
		}
1038
			return 0;
1039
1305
1040
		/* Now adjust the suffix of the hostname object. */
1306
		/* Now adjust the suffix of the hostname object. */
1041
		hn->suffix += ldiff;
1307
		hn->suffix += ldiff;
Lines 1051-1070 static int hostrange_hn_within(hostrange_t *hr, hostname_t *hn, int dims) Link Here
1051
1317
1052
		/* Now compare them and see if they match */
1318
		/* Now compare them and see if they match */
1053
		if (strcmp(hr->prefix, hn->prefix) != 0)
1319
		if (strcmp(hr->prefix, hn->prefix) != 0)
1054
			return 0;
1320
			goto free_cpy;
1055
	}
1321
	}
1056
1322
1323
	/* And check the suffix if any */
1324
	if (hr->suffix && hostname_suffix_extra(hn, dims) &&
1325
			strcmp(hr->suffix, hostname_suffix_extra(hn, dims)) != 0)
1326
		goto free_cpy;
1327
1057
	/*
1328
	/*
1058
	 *  Finally, check whether [hn], with a valid numeric suffix,
1329
	 *  Finally, check whether [hn], with a valid numeric suffix,
1059
	 *   falls within the range of [hr].
1330
	 *   falls within the range of [hr].
1060
	 */
1331
	 */
1061
	if (hn->num <= hr->hi && hn->num >= hr->lo) {
1332
	if (hn->num <= hr->hi && hn->num >= hr->lo) {
1062
		int width = hostname_suffix_width(hn);
1333
		int width = hostname_suffix_width(hn, dims);
1063
		int num = hn->num;
1334
		int num = hn->num;
1064
		return (_width_equiv(hr->lo, &hr->width, num, &width));
1335
		ret = (_width_equiv(hr->lo, &hr->width, num, &width));
1065
	}
1336
	}
1066
1337
1067
	return 0;
1338
free_cpy:
1339
	if (hn != hn_orig)
1340
		hostname_destroy(hn);
1341
	return ret;
1068
}
1342
}
1069
1343
1070
1344
Lines 1103-1108 static size_t hostrange_to_string(hostrange_t *hr, size_t n, char *buf, Link Here
1103
			int i2 = 0;
1377
			int i2 = 0;
1104
			int coord[dims];
1378
			int coord[dims];
1105
1379
1380
			xassert(!hr->suffix);
1106
			hostlist_parse_int_to_array(i, coord, dims, 0);
1381
			hostlist_parse_int_to_array(i, coord, dims, 0);
1107
			ret = snprintf(buf + len, n - len, "%s", hr->prefix);
1382
			ret = snprintf(buf + len, n - len, "%s", hr->prefix);
1108
			if (ret < 0 || (len += ret) >= n || len + dims >= n)
1383
			if (ret < 0 || (len += ret) >= n || len + dims >= n)
Lines 1110-1117 static size_t hostrange_to_string(hostrange_t *hr, size_t n, char *buf, Link Here
1110
			while (i2 < dims)
1385
			while (i2 < dims)
1111
				buf[len++] = alpha_num[coord[i2++]];
1386
				buf[len++] = alpha_num[coord[i2++]];
1112
		} else {
1387
		} else {
1113
			ret = snprintf(buf + len, n - len, "%s%0*lu",
1388
			ret = snprintf(buf + len, n - len, "%s%0*lu%s",
1114
				       hr->prefix, hr->width, i);
1389
				       hr->prefix, hr->width, i, hr->suffix ? hr->suffix : "");
1115
			if (ret < 0 || (len += ret) >= n)
1390
			if (ret < 0 || (len += ret) >= n)
1116
				goto truncated;
1391
				goto truncated;
1117
		}
1392
		}
Lines 1274-1280 static int hostlist_push_range(hostlist_t hl, hostrange_t *hr) Link Here
1274
1549
1275
	if (hl->nranges > 0
1550
	if (hl->nranges > 0
1276
	    && tail->hi == hr->lo - 1
1551
	    && tail->hi == hr->lo - 1
1277
	    && hostrange_prefix_cmp(tail, hr) == 0
1552
	    && hostrange_prefix_suffix_cmp(tail, hr) == 0
1278
	    && hostrange_width_combine(tail, hr)) {
1553
	    && hostrange_width_combine(tail, hr)) {
1279
		tail->hi = hr->hi;
1554
		tail->hi = hr->hi;
1280
	} else {
1555
	} else {
Lines 1302-1310 error: Link Here
1302
 */
1577
 */
1303
static int
1578
static int
1304
hostlist_push_hr(hostlist_t hl, char *prefix, unsigned long lo,
1579
hostlist_push_hr(hostlist_t hl, char *prefix, unsigned long lo,
1305
		 unsigned long hi, int width)
1580
		 unsigned long hi, int width, char *suffix)
1306
{
1581
{
1307
	hostrange_t *hr = hostrange_create(prefix, lo, hi, width);
1582
	hostrange_t *hr = hostrange_create(prefix, lo, hi, width, suffix);
1308
	int retval = hostlist_push_range(hl, hr);
1583
	int retval = hostlist_push_range(hl, hr);
1309
	hostrange_destroy(hr);
1584
	hostrange_destroy(hr);
1310
	return retval;
1585
	return retval;
Lines 1509-1515 hostlist_t _hostlist_create(const char *hostlist, char *sep, char *r_op, Link Here
1509
		} else {
1784
		} else {
1510
			if (high < low)
1785
			if (high < low)
1511
				high = low;
1786
				high = low;
1512
			hostlist_push_hr(new, prefix, low, high, fmt);
1787
			hostlist_push_hr(new, prefix, low, high, fmt, NULL);
1513
		}
1788
		}
1514
1789
1515
		error = 0;
1790
		error = 0;
Lines 1711-1717 static int _parse_range_list(char *str, Link Here
1711
 * RET 0 on success, -1 on failure (invalid prefix) */
1986
 * RET 0 on success, -1 on failure (invalid prefix) */
1712
static int
1987
static int
1713
_push_range_list(hostlist_t hl, char *prefix, struct _range *range,
1988
_push_range_list(hostlist_t hl, char *prefix, struct _range *range,
1714
		 int n, int dims)
1989
		 int n, int dims, char *suffix)
1715
{
1990
{
1716
	int i, k, nr, rc = 0, rc1;
1991
	int i, k, nr, rc = 0, rc1;
1717
	char *p, *q;
1992
	char *p, *q;
Lines 1749-1755 _push_range_list(hostlist_t hl, char *prefix, struct _range *range, Link Here
1749
				if (recurse) {
2024
				if (recurse) {
1750
					rc1 = _push_range_list(hl, new_prefix,
2025
					rc1 = _push_range_list(hl, new_prefix,
1751
							       saved_range,
2026
							       saved_range,
1752
							       n, dims);
2027
							       n, dims, suffix);
1753
					rc = MAX(rc, rc1);
2028
					rc = MAX(rc, rc1);
1754
				} else {
2029
				} else {
1755
					range = saved_range;
2030
					range = saved_range;
Lines 1757-1763 _push_range_list(hostlist_t hl, char *prefix, struct _range *range, Link Here
1757
						hostlist_push_hr(hl, new_prefix,
2032
						hostlist_push_hr(hl, new_prefix,
1758
								 range->lo,
2033
								 range->lo,
1759
								 range->hi,
2034
								 range->hi,
1760
								 range->width);
2035
								 range->width, suffix);
1761
						range++;
2036
						range++;
1762
					}
2037
					}
1763
				}
2038
				}
Lines 1771-1777 _push_range_list(hostlist_t hl, char *prefix, struct _range *range, Link Here
1771
2046
1772
	for (k = 0; k < n; k++) {
2047
	for (k = 0; k < n; k++) {
1773
		hostlist_push_hr(hl, prefix,
2048
		hostlist_push_hr(hl, prefix,
1774
				 range->lo, range->hi, range->width);
2049
				 range->lo, range->hi, range->width, suffix);
1775
		range++;
2050
		range++;
1776
	}
2051
	}
1777
	return 0;
2052
	return 0;
Lines 1801-1812 _hostlist_create_bracketed(const char *hostlist, char *sep, Link Here
1801
2076
1802
	while ((tok = _next_tok(sep, &str)) != NULL) {
2077
	while ((tok = _next_tok(sep, &str)) != NULL) {
1803
		if ((p = strrchr(tok, '[')) != NULL) {
2078
		if ((p = strrchr(tok, '[')) != NULL) {
1804
			char *q, *prefix = tok;
2079
			char *q, *prefix = tok, *suffix = NULL;
1805
			*p++ = '\0';
2080
			*p++ = '\0';
1806
2081
1807
			if ((q = strchr(p, ']'))) {
2082
			if ((q = strchr(p, ']'))) {
1808
				if ((q[1] != ',') && (q[1] != '\0'))
2083
				if ((q[1] != ',') && (q[1] != '\0')) {
1809
					goto error;
2084
					/* suffix only supported for dims == 1 */
2085
					if (dims == 1)
2086
						suffix = q+1;
2087
					else
2088
						goto error;
2089
				}
1810
				*q = '\0';
2090
				*q = '\0';
1811
				nr = _parse_range_list(p,
2091
				nr = _parse_range_list(p,
1812
						       &ranges,
2092
						       &ranges,
Lines 1815-1821 _hostlist_create_bracketed(const char *hostlist, char *sep, Link Here
1815
				if (nr < 0)
2095
				if (nr < 0)
1816
					goto error;
2096
					goto error;
1817
				if (_push_range_list(
2097
				if (_push_range_list(
1818
					    new, prefix, ranges, nr, dims))
2098
					    new, prefix, ranges, nr, dims, suffix))
1819
					goto error;
2099
					goto error;
1820
			} else {
2100
			} else {
1821
				/* The hostname itself contains a '['
2101
				/* The hostname itself contains a '['
Lines 1961-1967 int hostlist_push_host_dims(hostlist_t hl, const char *str, int dims) Link Here
1961
2241
1962
	if (hostname_suffix_is_valid(hn))
2242
	if (hostname_suffix_is_valid(hn))
1963
		hr = hostrange_create(hn->prefix, hn->num, hn->num,
2243
		hr = hostrange_create(hn->prefix, hn->num, hn->num,
1964
				      hostname_suffix_width(hn));
2244
				      hostname_suffix_width(hn, dims), hostname_suffix_extra(hn, dims));
1965
	else
2245
	else
1966
		hr = hostrange_create_single(str);
2246
		hr = hostrange_create_single(str);
1967
2247
Lines 2246-2251 static char *_hostrange_string(hostrange_t *hr, int depth) Link Here
2246
			int i2 = 0;
2526
			int i2 = 0;
2247
			int coord[dims];
2527
			int coord[dims];
2248
2528
2529
			xassert(!hr->suffix);
2249
			hostlist_parse_int_to_array(
2530
			hostlist_parse_int_to_array(
2250
				hr->lo + depth, coord, dims, 0);
2531
				hr->lo + depth, coord, dims, 0);
2251
2532
Lines 2253-2260 static char *_hostrange_string(hostrange_t *hr, int depth) Link Here
2253
				buf[len++] = alpha_num[coord[i2++]];
2534
				buf[len++] = alpha_num[coord[i2++]];
2254
			buf[len] = '\0';
2535
			buf[len] = '\0';
2255
		} else {
2536
		} else {
2256
			len = snprintf(buf + len, size - len, "%0*lu",
2537
			len = snprintf(buf + len, size - len, "%0*lu%s",
2257
				       hr->width, hr->lo + depth);
2538
				       hr->width, hr->lo + depth, hr->suffix ? hr->suffix : "");
2258
			if (len < 0 || len >= size)
2539
			if (len < 0 || len >= size)
2259
				return NULL;
2540
				return NULL;
2260
		}
2541
		}
Lines 2424-2431 static void hostlist_collapse(hostlist_t hl) Link Here
2424
		hostrange_t *hprev = hl->hr[i - 1];
2705
		hostrange_t *hprev = hl->hr[i - 1];
2425
		hostrange_t *hnext = hl->hr[i];
2706
		hostrange_t *hnext = hl->hr[i];
2426
2707
2427
		if (hprev->hi == hnext->lo - 1 &&
2708
		if ((hprev->hi == hnext->lo - 1 || hprev->hi == hnext->lo) &&
2428
		    hostrange_prefix_cmp(hprev, hnext) == 0 &&
2709
		    hostrange_prefix_suffix_cmp(hprev, hnext) == 0 &&
2429
		    hostrange_width_combine(hprev, hnext)) {
2710
		    hostrange_width_combine(hprev, hnext)) {
2430
			hprev->hi = hnext->hi;
2711
			hprev->hi = hnext->hi;
2431
			hostlist_delete_range(hl, i);
2712
			hostlist_delete_range(hl, i);
Lines 2444-2449 static void hostlist_coalesce(hostlist_t hl) Link Here
2444
2725
2445
	LOCK_HOSTLIST(hl);
2726
	LOCK_HOSTLIST(hl);
2446
2727
2728
    for (i = 0; i < hl->nranges - 1; i++) {
2729
        new = hostrange_combine_suffix(hl->hr[i], hl->hr[i+1]);
2730
        if (new) {
2731
            /* combined, we can delete the second range */
2732
            hostlist_delete_range(hl, i+1);
2733
			/* try to combine this one with the next one again */
2734
			i--;
2735
        }
2736
    }
2737
2447
	for (i = hl->nranges - 1; i > 0; i--) {
2738
	for (i = hl->nranges - 1; i > 0; i--) {
2448
2739
2449
		new = hostrange_intersect(hl->hr[i - 1], hl->hr[i]);
2740
		new = hostrange_intersect(hl->hr[i - 1], hl->hr[i]);
Lines 2465-2471 static void hostlist_coalesce(hostlist_t hl) Link Here
2465
			while (new->lo <= new->hi) {
2756
			while (new->lo <= new->hi) {
2466
				hostrange_t *hr = hostrange_create(new->prefix,
2757
				hostrange_t *hr = hostrange_create(new->prefix,
2467
								   new->lo, new->lo,
2758
								   new->lo, new->lo,
2468
								   new->width);
2759
								   new->width, new->suffix);
2469
2760
2470
				if (new->lo > hprev->hi)
2761
				if (new->lo > hprev->hi)
2471
					hostlist_insert_range(hl, hr, j++);
2762
					hostlist_insert_range(hl, hr, j++);
Lines 2624-2630 _get_bracketed_list(hostlist_t hl, int *start, const size_t n, char *buf, Link Here
2624
		    int brackets)
2915
		    int brackets)
2625
{
2916
{
2626
	hostrange_t **hr = hl->hr;
2917
	hostrange_t **hr = hl->hr;
2627
	int i = *start;
2918
	int i = *start, first = *start;
2628
	int m, len = 0;
2919
	int m, len = 0;
2629
	int bracket_needed = brackets ? _is_bracket_needed(hl, i) : 0;
2920
	int bracket_needed = brackets ? _is_bracket_needed(hl, i) : 0;
2630
	int zeropad = 0;
2921
	int zeropad = 0;
Lines 2670-2675 _get_bracketed_list(hostlist_t hl, int *start, const size_t n, char *buf, Link Here
2670
	if (bracket_needed)
2961
	if (bracket_needed)
2671
		buf[len++] = ']';
2962
		buf[len++] = ']';
2672
2963
2964
	/* All grouped ranges should have the same suffix, use the first */
2965
	if (hr[first]->suffix) {
2966
		xassert(n - len > 1);
2967
		len += snprintf(buf + len, n - len - 1, "%s", hr[first]->suffix);
2968
		if (n - len < 1)    /* no space left in buffer */
2969
			return len;
2970
	}
2971
2673
	buf[len] = '\0';
2972
	buf[len] = '\0';
2674
	*start = i;
2973
	*start = i;
2675
	return len;
2974
	return len;
Lines 3374-3379 char *hostlist_next_dims(hostlist_iterator_t i, int dims) Link Here
3374
				       i->hr->width, i->hr->lo + i->depth);
3673
				       i->hr->width, i->hr->lo + i->depth);
3375
			if (len < 0 || len >= size)
3674
			if (len < 0 || len >= size)
3376
				goto no_next;
3675
				goto no_next;
3676
			if (i->hr->suffix) {
3677
				len += snprintf(buf + len, size - len, "%s", i->hr->suffix);
3678
				if (len < 0 || len >= size)
3679
					goto no_next;
3680
			}
3377
		}
3681
		}
3378
	}
3682
	}
3379
	UNLOCK_HOSTLIST(i->hl);
3683
	UNLOCK_HOSTLIST(i->hl);
(-)a/testsuite/slurm_unit/common/hostlist/hostlist_nth-test.c (-1 / +56 lines)
Lines 36-41 Link Here
36
#include <stdio.h>
36
#include <stdio.h>
37
#include <stdlib.h>
37
#include <stdlib.h>
38
#include <signal.h>
38
#include <signal.h>
39
#include <assert.h>
39
40
40
#include "slurm/slurm.h"
41
#include "slurm/slurm.h"
41
#include "src/common/hostlist.h"
42
#include "src/common/hostlist.h"
Lines 48-53 hostset_t slurm_hostset_create(const char*); Link Here
48
void slurm_hostset_destroy(hostset_t);
49
void slurm_hostset_destroy(hostset_t);
49
int slurm_hostset_count(hostset_t);
50
int slurm_hostset_count(hostset_t);
50
51
52
#define ck_assert_ptr_ne(p1, p2)    ck_assert_int_ne((long int)p1, (long int)p2)
53
#define ck_assert_ptr_eq(p1, p2)    ck_assert_int_eq((long int)p1, (long int)p2)
54
51
#ifndef NDEBUG
55
#ifndef NDEBUG
52
/* note: only works in CK_FORK mode */
56
/* note: only works in CK_FORK mode */
53
START_TEST(hostlist_nth_lo_assert_check)
57
START_TEST(hostlist_nth_lo_assert_check)
Lines 120-125 START_TEST(hostlist_nth_check) Link Here
120
}
124
}
121
END_TEST
125
END_TEST
122
126
127
START_TEST(hostlist_suffix_check)
128
{
129
	hostlist_t hl = NULL;
130
	char *p;
131
	int n, i;
132
	char hspec[] = "host4-abc,host[1-3]-abc,host6-abc,host7";
133
	char expect_spec[] = "host7,host[1-4,6]-abc";
134
	char *buf;
135
136
	ck_assert_ptr_eq(slurm_hostlist_nth(hl, 0), NULL);
137
138
	hl = slurm_hostlist_create(hspec);
139
	ck_assert_ptr_ne(hl, NULL);
140
141
	n = slurm_hostlist_count(hl);
142
	ck_assert_int_eq(n, 6);
143
144
	hostlist_sort(hl);
145
146
	n = slurm_hostlist_count(hl);
147
	ck_assert_int_eq(n, 6);
148
149
	buf = hostlist_ranged_string_malloc(hl);
150
	ck_assert_str_eq(buf, expect_spec);
151
	free(buf);
152
153
	p = slurm_hostlist_nth(hl, 0);
154
	ck_assert_str_eq(p, "host7");
155
	free(p);
156
157
	for (i = 1; i < 5; i++) {
158
		char host_str[16];
159
		sprintf(host_str, "host%d-abc", i);
160
		p = slurm_hostlist_nth(hl, i);
161
		ck_assert_str_eq(p, host_str);
162
		free(p);
163
	}
164
165
	p = slurm_hostlist_nth(hl, 5);
166
	ck_assert_str_eq(p, "host6-abc");
167
	free(p);
168
169
	for (i = 0; i < n; i++) {
170
		ck_assert_int_eq(slurm_hostlist_delete_nth(hl, 0), 1);
171
		ck_assert_int_eq(slurm_hostlist_count(hl), n-i-1);
172
	}
173
174
	slurm_hostlist_destroy(hl);
175
}
176
END_TEST
177
123
START_TEST(hostset_nth_check)
178
START_TEST(hostset_nth_check)
124
{
179
{
125
	hostset_t hs;
180
	hostset_t hs;
Lines 154-159 Suite *make_nonassert_suite(void) Link Here
154
	TCase *tc_core = tcase_create("host_nth_check_nonassert");
209
	TCase *tc_core = tcase_create("host_nth_check_nonassert");
155
	tcase_add_test(tc_core, hostlist_nth_check);
210
	tcase_add_test(tc_core, hostlist_nth_check);
156
	tcase_add_test(tc_core, hostset_nth_check);
211
	tcase_add_test(tc_core, hostset_nth_check);
212
	tcase_add_test(tc_core, hostlist_suffix_check);
157
	suite_add_tcase(s, tc_core);
213
	suite_add_tcase(s, tc_core);
158
	return s;
214
	return s;
159
}
215
}
160
- 

Return to ticket 13749