Source file src/text/tabwriter/tabwriter_test.go

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package tabwriter_test
     6  
     7  import (
     8  	"bytes"
     9  	"fmt"
    10  	"io"
    11  	"testing"
    12  	. "text/tabwriter"
    13  )
    14  
    15  type buffer struct {
    16  	a []byte
    17  }
    18  
    19  func (b *buffer) init(n int) { b.a = make([]byte, 0, n) }
    20  
    21  func (b *buffer) clear() { b.a = b.a[0:0] }
    22  
    23  func (b *buffer) Write(buf []byte) (written int, err error) {
    24  	n := len(b.a)
    25  	m := len(buf)
    26  	if n+m <= cap(b.a) {
    27  		b.a = b.a[0 : n+m]
    28  		for i := 0; i < m; i++ {
    29  			b.a[n+i] = buf[i]
    30  		}
    31  	} else {
    32  		panic("buffer.Write: buffer too small")
    33  	}
    34  	return len(buf), nil
    35  }
    36  
    37  func (b *buffer) String() string { return string(b.a) }
    38  
    39  func write(t *testing.T, testname string, w *Writer, src string) {
    40  	written, err := io.WriteString(w, src)
    41  	if err != nil {
    42  		t.Errorf("--- test: %s\n--- src:\n%q\n--- write error: %v\n", testname, src, err)
    43  	}
    44  	if written != len(src) {
    45  		t.Errorf("--- test: %s\n--- src:\n%q\n--- written = %d, len(src) = %d\n", testname, src, written, len(src))
    46  	}
    47  }
    48  
    49  func verify(t *testing.T, testname string, w *Writer, b *buffer, src, expected string) {
    50  	err := w.Flush()
    51  	if err != nil {
    52  		t.Errorf("--- test: %s\n--- src:\n%q\n--- flush error: %v\n", testname, src, err)
    53  	}
    54  
    55  	res := b.String()
    56  	if res != expected {
    57  		t.Errorf("--- test: %s\n--- src:\n%q\n--- found:\n%q\n--- expected:\n%q\n", testname, src, res, expected)
    58  	}
    59  }
    60  
    61  func check(t *testing.T, testname string, minwidth, tabwidth, padding int, padchar byte, flags uint, src, expected string) {
    62  	var b buffer
    63  	b.init(1000)
    64  
    65  	var w Writer
    66  	w.Init(&b, minwidth, tabwidth, padding, padchar, flags)
    67  
    68  	// write all at once
    69  	title := testname + " (written all at once)"
    70  	b.clear()
    71  	write(t, title, &w, src)
    72  	verify(t, title, &w, &b, src, expected)
    73  
    74  	// write byte-by-byte
    75  	title = testname + " (written byte-by-byte)"
    76  	b.clear()
    77  	for i := 0; i < len(src); i++ {
    78  		write(t, title, &w, src[i:i+1])
    79  	}
    80  	verify(t, title, &w, &b, src, expected)
    81  
    82  	// write using Fibonacci slice sizes
    83  	title = testname + " (written in fibonacci slices)"
    84  	b.clear()
    85  	for i, d := 0, 0; i < len(src); {
    86  		write(t, title, &w, src[i:i+d])
    87  		i, d = i+d, d+1
    88  		if i+d > len(src) {
    89  			d = len(src) - i
    90  		}
    91  	}
    92  	verify(t, title, &w, &b, src, expected)
    93  }
    94  
    95  var tests = []struct {
    96  	testname                    string
    97  	minwidth, tabwidth, padding int
    98  	padchar                     byte
    99  	flags                       uint
   100  	src, expected               string
   101  }{
   102  	{
   103  		"1a",
   104  		8, 0, 1, '.', 0,
   105  		"",
   106  		"",
   107  	},
   108  
   109  	{
   110  		"1a debug",
   111  		8, 0, 1, '.', Debug,
   112  		"",
   113  		"",
   114  	},
   115  
   116  	{
   117  		"1b esc stripped",
   118  		8, 0, 1, '.', StripEscape,
   119  		"\xff\xff",
   120  		"",
   121  	},
   122  
   123  	{
   124  		"1b esc",
   125  		8, 0, 1, '.', 0,
   126  		"\xff\xff",
   127  		"\xff\xff",
   128  	},
   129  
   130  	{
   131  		"1c esc stripped",
   132  		8, 0, 1, '.', StripEscape,
   133  		"\xff\t\xff",
   134  		"\t",
   135  	},
   136  
   137  	{
   138  		"1c esc",
   139  		8, 0, 1, '.', 0,
   140  		"\xff\t\xff",
   141  		"\xff\t\xff",
   142  	},
   143  
   144  	{
   145  		"1d esc stripped",
   146  		8, 0, 1, '.', StripEscape,
   147  		"\xff\"foo\t\n\tbar\"\xff",
   148  		"\"foo\t\n\tbar\"",
   149  	},
   150  
   151  	{
   152  		"1d esc",
   153  		8, 0, 1, '.', 0,
   154  		"\xff\"foo\t\n\tbar\"\xff",
   155  		"\xff\"foo\t\n\tbar\"\xff",
   156  	},
   157  
   158  	{
   159  		"1e esc stripped",
   160  		8, 0, 1, '.', StripEscape,
   161  		"abc\xff\tdef", // unterminated escape
   162  		"abc\tdef",
   163  	},
   164  
   165  	{
   166  		"1e esc",
   167  		8, 0, 1, '.', 0,
   168  		"abc\xff\tdef", // unterminated escape
   169  		"abc\xff\tdef",
   170  	},
   171  
   172  	{
   173  		"2",
   174  		8, 0, 1, '.', 0,
   175  		"\n\n\n",
   176  		"\n\n\n",
   177  	},
   178  
   179  	{
   180  		"3",
   181  		8, 0, 1, '.', 0,
   182  		"a\nb\nc",
   183  		"a\nb\nc",
   184  	},
   185  
   186  	{
   187  		"4a",
   188  		8, 0, 1, '.', 0,
   189  		"\t", // '\t' terminates an empty cell on last line - nothing to print
   190  		"",
   191  	},
   192  
   193  	{
   194  		"4b",
   195  		8, 0, 1, '.', AlignRight,
   196  		"\t", // '\t' terminates an empty cell on last line - nothing to print
   197  		"",
   198  	},
   199  
   200  	{
   201  		"5",
   202  		8, 0, 1, '.', 0,
   203  		"*\t*",
   204  		"*.......*",
   205  	},
   206  
   207  	{
   208  		"5b",
   209  		8, 0, 1, '.', 0,
   210  		"*\t*\n",
   211  		"*.......*\n",
   212  	},
   213  
   214  	{
   215  		"5c",
   216  		8, 0, 1, '.', 0,
   217  		"*\t*\t",
   218  		"*.......*",
   219  	},
   220  
   221  	{
   222  		"5c debug",
   223  		8, 0, 1, '.', Debug,
   224  		"*\t*\t",
   225  		"*.......|*",
   226  	},
   227  
   228  	{
   229  		"5d",
   230  		8, 0, 1, '.', AlignRight,
   231  		"*\t*\t",
   232  		".......**",
   233  	},
   234  
   235  	{
   236  		"6",
   237  		8, 0, 1, '.', 0,
   238  		"\t\n",
   239  		"........\n",
   240  	},
   241  
   242  	{
   243  		"7a",
   244  		8, 0, 1, '.', 0,
   245  		"a) foo",
   246  		"a) foo",
   247  	},
   248  
   249  	{
   250  		"7b",
   251  		8, 0, 1, ' ', 0,
   252  		"b) foo\tbar",
   253  		"b) foo  bar",
   254  	},
   255  
   256  	{
   257  		"7c",
   258  		8, 0, 1, '.', 0,
   259  		"c) foo\tbar\t",
   260  		"c) foo..bar",
   261  	},
   262  
   263  	{
   264  		"7d",
   265  		8, 0, 1, '.', 0,
   266  		"d) foo\tbar\n",
   267  		"d) foo..bar\n",
   268  	},
   269  
   270  	{
   271  		"7e",
   272  		8, 0, 1, '.', 0,
   273  		"e) foo\tbar\t\n",
   274  		"e) foo..bar.....\n",
   275  	},
   276  
   277  	{
   278  		"7f",
   279  		8, 0, 1, '.', FilterHTML,
   280  		"f) f&lt;o\t<b>bar</b>\t\n",
   281  		"f) f&lt;o..<b>bar</b>.....\n",
   282  	},
   283  
   284  	{
   285  		"7g",
   286  		8, 0, 1, '.', FilterHTML,
   287  		"g) f&lt;o\t<b>bar</b>\t non-terminated entity &amp",
   288  		"g) f&lt;o..<b>bar</b>..... non-terminated entity &amp",
   289  	},
   290  
   291  	{
   292  		"7g debug",
   293  		8, 0, 1, '.', FilterHTML | Debug,
   294  		"g) f&lt;o\t<b>bar</b>\t non-terminated entity &amp",
   295  		"g) f&lt;o..|<b>bar</b>.....| non-terminated entity &amp",
   296  	},
   297  
   298  	{
   299  		"8",
   300  		8, 0, 1, '*', 0,
   301  		"Hello, world!\n",
   302  		"Hello, world!\n",
   303  	},
   304  
   305  	{
   306  		"9a",
   307  		1, 0, 0, '.', 0,
   308  		"1\t2\t3\t4\n" +
   309  			"11\t222\t3333\t44444\n",
   310  
   311  		"1.2..3...4\n" +
   312  			"11222333344444\n",
   313  	},
   314  
   315  	{
   316  		"9b",
   317  		1, 0, 0, '.', FilterHTML,
   318  		"1\t2<!---\f--->\t3\t4\n" + // \f inside HTML is ignored
   319  			"11\t222\t3333\t44444\n",
   320  
   321  		"1.2<!---\f--->..3...4\n" +
   322  			"11222333344444\n",
   323  	},
   324  
   325  	{
   326  		"9c",
   327  		1, 0, 0, '.', 0,
   328  		"1\t2\t3\t4\f" + // \f causes a newline and flush
   329  			"11\t222\t3333\t44444\n",
   330  
   331  		"1234\n" +
   332  			"11222333344444\n",
   333  	},
   334  
   335  	{
   336  		"9c debug",
   337  		1, 0, 0, '.', Debug,
   338  		"1\t2\t3\t4\f" + // \f causes a newline and flush
   339  			"11\t222\t3333\t44444\n",
   340  
   341  		"1|2|3|4\n" +
   342  			"---\n" +
   343  			"11|222|3333|44444\n",
   344  	},
   345  
   346  	{
   347  		"10a",
   348  		5, 0, 0, '.', 0,
   349  		"1\t2\t3\t4\n",
   350  		"1....2....3....4\n",
   351  	},
   352  
   353  	{
   354  		"10b",
   355  		5, 0, 0, '.', 0,
   356  		"1\t2\t3\t4\t\n",
   357  		"1....2....3....4....\n",
   358  	},
   359  
   360  	{
   361  		"11",
   362  		8, 0, 1, '.', 0,
   363  		"本\tb\tc\n" +
   364  			"aa\t\u672c\u672c\u672c\tcccc\tddddd\n" +
   365  			"aaa\tbbbb\n",
   366  
   367  		"本.......b.......c\n" +
   368  			"aa......本本本.....cccc....ddddd\n" +
   369  			"aaa.....bbbb\n",
   370  	},
   371  
   372  	{
   373  		"12a",
   374  		8, 0, 1, ' ', AlignRight,
   375  		"a\tè\tc\t\n" +
   376  			"aa\tèèè\tcccc\tddddd\t\n" +
   377  			"aaa\tèèèè\t\n",
   378  
   379  		"       a       è       c\n" +
   380  			"      aa     èèè    cccc   ddddd\n" +
   381  			"     aaa    èèèè\n",
   382  	},
   383  
   384  	{
   385  		"12b",
   386  		2, 0, 0, ' ', 0,
   387  		"a\tb\tc\n" +
   388  			"aa\tbbb\tcccc\n" +
   389  			"aaa\tbbbb\n",
   390  
   391  		"a  b  c\n" +
   392  			"aa bbbcccc\n" +
   393  			"aaabbbb\n",
   394  	},
   395  
   396  	{
   397  		"12c",
   398  		8, 0, 1, '_', 0,
   399  		"a\tb\tc\n" +
   400  			"aa\tbbb\tcccc\n" +
   401  			"aaa\tbbbb\n",
   402  
   403  		"a_______b_______c\n" +
   404  			"aa______bbb_____cccc\n" +
   405  			"aaa_____bbbb\n",
   406  	},
   407  
   408  	{
   409  		"13a",
   410  		4, 0, 1, '-', 0,
   411  		"4444\t日本語\t22\t1\t333\n" +
   412  			"999999999\t22\n" +
   413  			"7\t22\n" +
   414  			"\t\t\t88888888\n" +
   415  			"\n" +
   416  			"666666\t666666\t666666\t4444\n" +
   417  			"1\t1\t999999999\t0000000000\n",
   418  
   419  		"4444------日本語-22--1---333\n" +
   420  			"999999999-22\n" +
   421  			"7---------22\n" +
   422  			"------------------88888888\n" +
   423  			"\n" +
   424  			"666666-666666-666666----4444\n" +
   425  			"1------1------999999999-0000000000\n",
   426  	},
   427  
   428  	{
   429  		"13b",
   430  		4, 0, 3, '.', 0,
   431  		"4444\t333\t22\t1\t333\n" +
   432  			"999999999\t22\n" +
   433  			"7\t22\n" +
   434  			"\t\t\t88888888\n" +
   435  			"\n" +
   436  			"666666\t666666\t666666\t4444\n" +
   437  			"1\t1\t999999999\t0000000000\n",
   438  
   439  		"4444........333...22...1...333\n" +
   440  			"999999999...22\n" +
   441  			"7...........22\n" +
   442  			"....................88888888\n" +
   443  			"\n" +
   444  			"666666...666666...666666......4444\n" +
   445  			"1........1........999999999...0000000000\n",
   446  	},
   447  
   448  	{
   449  		"13c",
   450  		8, 8, 1, '\t', FilterHTML,
   451  		"4444\t333\t22\t1\t333\n" +
   452  			"999999999\t22\n" +
   453  			"7\t22\n" +
   454  			"\t\t\t88888888\n" +
   455  			"\n" +
   456  			"666666\t666666\t666666\t4444\n" +
   457  			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
   458  
   459  		"4444\t\t333\t22\t1\t333\n" +
   460  			"999999999\t22\n" +
   461  			"7\t\t22\n" +
   462  			"\t\t\t\t88888888\n" +
   463  			"\n" +
   464  			"666666\t666666\t666666\t\t4444\n" +
   465  			"1\t1\t<font color=red attr=日本語>999999999</font>\t0000000000\n",
   466  	},
   467  
   468  	{
   469  		"14",
   470  		1, 0, 2, ' ', AlignRight,
   471  		".0\t.3\t2.4\t-5.1\t\n" +
   472  			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
   473  			"5.1\t12.0\t2.4\t-7.0\t\n" +
   474  			".0\t0.0\t332.0\t8908.0\t\n" +
   475  			".0\t-.3\t456.4\t22.1\t\n" +
   476  			".0\t1.2\t44.4\t-13.3\t\t",
   477  
   478  		"    .0          .3    2.4    -5.1\n" +
   479  			"  23.0  12345678.9    2.4  -989.4\n" +
   480  			"   5.1        12.0    2.4    -7.0\n" +
   481  			"    .0         0.0  332.0  8908.0\n" +
   482  			"    .0         -.3  456.4    22.1\n" +
   483  			"    .0         1.2   44.4   -13.3",
   484  	},
   485  
   486  	{
   487  		"14 debug",
   488  		1, 0, 2, ' ', AlignRight | Debug,
   489  		".0\t.3\t2.4\t-5.1\t\n" +
   490  			"23.0\t12345678.9\t2.4\t-989.4\t\n" +
   491  			"5.1\t12.0\t2.4\t-7.0\t\n" +
   492  			".0\t0.0\t332.0\t8908.0\t\n" +
   493  			".0\t-.3\t456.4\t22.1\t\n" +
   494  			".0\t1.2\t44.4\t-13.3\t\t",
   495  
   496  		"    .0|          .3|    2.4|    -5.1|\n" +
   497  			"  23.0|  12345678.9|    2.4|  -989.4|\n" +
   498  			"   5.1|        12.0|    2.4|    -7.0|\n" +
   499  			"    .0|         0.0|  332.0|  8908.0|\n" +
   500  			"    .0|         -.3|  456.4|    22.1|\n" +
   501  			"    .0|         1.2|   44.4|   -13.3|",
   502  	},
   503  
   504  	{
   505  		"15a",
   506  		4, 0, 0, '.', 0,
   507  		"a\t\tb",
   508  		"a.......b",
   509  	},
   510  
   511  	{
   512  		"15b",
   513  		4, 0, 0, '.', DiscardEmptyColumns,
   514  		"a\t\tb", // htabs - do not discard column
   515  		"a.......b",
   516  	},
   517  
   518  	{
   519  		"15c",
   520  		4, 0, 0, '.', DiscardEmptyColumns,
   521  		"a\v\vb",
   522  		"a...b",
   523  	},
   524  
   525  	{
   526  		"15d",
   527  		4, 0, 0, '.', AlignRight | DiscardEmptyColumns,
   528  		"a\v\vb",
   529  		"...ab",
   530  	},
   531  
   532  	{
   533  		"16a",
   534  		100, 100, 0, '\t', 0,
   535  		"a\tb\t\td\n" +
   536  			"a\tb\t\td\te\n" +
   537  			"a\n" +
   538  			"a\tb\tc\td\n" +
   539  			"a\tb\tc\td\te\n",
   540  
   541  		"a\tb\t\td\n" +
   542  			"a\tb\t\td\te\n" +
   543  			"a\n" +
   544  			"a\tb\tc\td\n" +
   545  			"a\tb\tc\td\te\n",
   546  	},
   547  
   548  	{
   549  		"16b",
   550  		100, 100, 0, '\t', DiscardEmptyColumns,
   551  		"a\vb\v\vd\n" +
   552  			"a\vb\v\vd\ve\n" +
   553  			"a\n" +
   554  			"a\vb\vc\vd\n" +
   555  			"a\vb\vc\vd\ve\n",
   556  
   557  		"a\tb\td\n" +
   558  			"a\tb\td\te\n" +
   559  			"a\n" +
   560  			"a\tb\tc\td\n" +
   561  			"a\tb\tc\td\te\n",
   562  	},
   563  
   564  	{
   565  		"16b debug",
   566  		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
   567  		"a\vb\v\vd\n" +
   568  			"a\vb\v\vd\ve\n" +
   569  			"a\n" +
   570  			"a\vb\vc\vd\n" +
   571  			"a\vb\vc\vd\ve\n",
   572  
   573  		"a\t|b\t||d\n" +
   574  			"a\t|b\t||d\t|e\n" +
   575  			"a\n" +
   576  			"a\t|b\t|c\t|d\n" +
   577  			"a\t|b\t|c\t|d\t|e\n",
   578  	},
   579  
   580  	{
   581  		"16c",
   582  		100, 100, 0, '\t', DiscardEmptyColumns,
   583  		"a\tb\t\td\n" + // hard tabs - do not discard column
   584  			"a\tb\t\td\te\n" +
   585  			"a\n" +
   586  			"a\tb\tc\td\n" +
   587  			"a\tb\tc\td\te\n",
   588  
   589  		"a\tb\t\td\n" +
   590  			"a\tb\t\td\te\n" +
   591  			"a\n" +
   592  			"a\tb\tc\td\n" +
   593  			"a\tb\tc\td\te\n",
   594  	},
   595  
   596  	{
   597  		"16c debug",
   598  		100, 100, 0, '\t', DiscardEmptyColumns | Debug,
   599  		"a\tb\t\td\n" + // hard tabs - do not discard column
   600  			"a\tb\t\td\te\n" +
   601  			"a\n" +
   602  			"a\tb\tc\td\n" +
   603  			"a\tb\tc\td\te\n",
   604  
   605  		"a\t|b\t|\t|d\n" +
   606  			"a\t|b\t|\t|d\t|e\n" +
   607  			"a\n" +
   608  			"a\t|b\t|c\t|d\n" +
   609  			"a\t|b\t|c\t|d\t|e\n",
   610  	},
   611  }
   612  
   613  func Test(t *testing.T) {
   614  	for _, e := range tests {
   615  		check(t, e.testname, e.minwidth, e.tabwidth, e.padding, e.padchar, e.flags, e.src, e.expected)
   616  	}
   617  }
   618  
   619  type panicWriter struct{}
   620  
   621  func (panicWriter) Write([]byte) (int, error) {
   622  	panic("cannot write")
   623  }
   624  
   625  func wantPanicString(t *testing.T, want string) {
   626  	if e := recover(); e != nil {
   627  		got, ok := e.(string)
   628  		switch {
   629  		case !ok:
   630  			t.Errorf("got %v (%T), want panic string", e, e)
   631  		case got != want:
   632  			t.Errorf("wrong panic message: got %q, want %q", got, want)
   633  		}
   634  	}
   635  }
   636  
   637  func TestPanicDuringFlush(t *testing.T) {
   638  	defer wantPanicString(t, "tabwriter: panic during Flush")
   639  	var p panicWriter
   640  	w := new(Writer)
   641  	w.Init(p, 0, 0, 5, ' ', 0)
   642  	io.WriteString(w, "a")
   643  	w.Flush()
   644  	t.Errorf("failed to panic during Flush")
   645  }
   646  
   647  func TestPanicDuringWrite(t *testing.T) {
   648  	defer wantPanicString(t, "tabwriter: panic during Write")
   649  	var p panicWriter
   650  	w := new(Writer)
   651  	w.Init(p, 0, 0, 5, ' ', 0)
   652  	io.WriteString(w, "a\n\n") // the second \n triggers a call to w.Write and thus a panic
   653  	t.Errorf("failed to panic during Write")
   654  }
   655  
   656  func BenchmarkTable(b *testing.B) {
   657  	for _, w := range [...]int{1, 10, 100} {
   658  		// Build a line with w cells.
   659  		line := bytes.Repeat([]byte("a\t"), w)
   660  		line = append(line, '\n')
   661  		for _, h := range [...]int{10, 1000, 100000} {
   662  			b.Run(fmt.Sprintf("%dx%d", w, h), func(b *testing.B) {
   663  				b.Run("new", func(b *testing.B) {
   664  					b.ReportAllocs()
   665  					for i := 0; i < b.N; i++ {
   666  						w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
   667  						// Write the line h times.
   668  						for j := 0; j < h; j++ {
   669  							w.Write(line)
   670  						}
   671  						w.Flush()
   672  					}
   673  				})
   674  
   675  				b.Run("reuse", func(b *testing.B) {
   676  					b.ReportAllocs()
   677  					w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
   678  					for i := 0; i < b.N; i++ {
   679  						// Write the line h times.
   680  						for j := 0; j < h; j++ {
   681  							w.Write(line)
   682  						}
   683  						w.Flush()
   684  					}
   685  				})
   686  			})
   687  		}
   688  	}
   689  }
   690  
   691  func BenchmarkPyramid(b *testing.B) {
   692  	for _, x := range [...]int{10, 100, 1000} {
   693  		// Build a line with x cells.
   694  		line := bytes.Repeat([]byte("a\t"), x)
   695  		b.Run(fmt.Sprintf("%d", x), func(b *testing.B) {
   696  			b.ReportAllocs()
   697  			for i := 0; i < b.N; i++ {
   698  				w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
   699  				// Write increasing prefixes of that line.
   700  				for j := 0; j < x; j++ {
   701  					w.Write(line[:j*2])
   702  					w.Write([]byte{'\n'})
   703  				}
   704  				w.Flush()
   705  			}
   706  		})
   707  	}
   708  }
   709  
   710  func BenchmarkRagged(b *testing.B) {
   711  	var lines [8][]byte
   712  	for i, w := range [8]int{6, 2, 9, 5, 5, 7, 3, 8} {
   713  		// Build a line with w cells.
   714  		lines[i] = bytes.Repeat([]byte("a\t"), w)
   715  	}
   716  	for _, h := range [...]int{10, 100, 1000} {
   717  		b.Run(fmt.Sprintf("%d", h), func(b *testing.B) {
   718  			b.ReportAllocs()
   719  			for i := 0; i < b.N; i++ {
   720  				w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
   721  				// Write the lines in turn h times.
   722  				for j := 0; j < h; j++ {
   723  					w.Write(lines[j%len(lines)])
   724  					w.Write([]byte{'\n'})
   725  				}
   726  				w.Flush()
   727  			}
   728  		})
   729  	}
   730  }
   731  
   732  const codeSnippet = `
   733  some command
   734  
   735  foo	# aligned
   736  barbaz	# comments
   737  
   738  but
   739  mostly
   740  single
   741  cell
   742  lines
   743  `
   744  
   745  func BenchmarkCode(b *testing.B) {
   746  	b.ReportAllocs()
   747  	for i := 0; i < b.N; i++ {
   748  		w := NewWriter(io.Discard, 4, 4, 1, ' ', 0) // no particular reason for these settings
   749  		// The code is small, so it's reasonable for the tabwriter user
   750  		// to write it all at once, or buffer the writes.
   751  		w.Write([]byte(codeSnippet))
   752  		w.Flush()
   753  	}
   754  }
   755  

View as plain text