@@ -38,21 +38,25 @@ class ExternalSorterSuite extends FunSuite with LocalSparkContext {
3838 val sorter = new ExternalSorter [Int , Int , Int ](
3939 Some (agg), Some (new HashPartitioner (3 )), Some (ord), None )
4040 assert(sorter.iterator.toSeq === Seq ())
41+ sorter.stop()
4142
4243 // Only aggregator
4344 val sorter2 = new ExternalSorter [Int , Int , Int ](
4445 Some (agg), Some (new HashPartitioner (3 )), None , None )
4546 assert(sorter2.iterator.toSeq === Seq ())
47+ sorter2.stop()
4648
4749 // Only ordering
4850 val sorter3 = new ExternalSorter [Int , Int , Int ](
4951 None , Some (new HashPartitioner (3 )), Some (ord), None )
5052 assert(sorter3.iterator.toSeq === Seq ())
53+ sorter3.stop()
5154
5255 // Neither aggregator nor ordering
5356 val sorter4 = new ExternalSorter [Int , Int , Int ](
5457 None , Some (new HashPartitioner (3 )), None , None )
5558 assert(sorter4.iterator.toSeq === Seq ())
59+ sorter4.stop()
5660 }
5761
5862 test(" few elements per partition" ) {
@@ -73,24 +77,53 @@ class ExternalSorterSuite extends FunSuite with LocalSparkContext {
7377 Some (agg), Some (new HashPartitioner (7 )), Some (ord), None )
7478 sorter.write(elements.iterator)
7579 assert(sorter.partitionedIterator.map(p => (p._1, p._2.toSet)).toSet === expected)
80+ sorter.stop()
7681
7782 // Only aggregator
7883 val sorter2 = new ExternalSorter [Int , Int , Int ](
7984 Some (agg), Some (new HashPartitioner (7 )), None , None )
8085 sorter2.write(elements.iterator)
8186 assert(sorter2.partitionedIterator.map(p => (p._1, p._2.toSet)).toSet === expected)
87+ sorter2.stop()
8288
8389 // Only ordering
8490 val sorter3 = new ExternalSorter [Int , Int , Int ](
8591 None , Some (new HashPartitioner (7 )), Some (ord), None )
8692 sorter3.write(elements.iterator)
8793 assert(sorter3.partitionedIterator.map(p => (p._1, p._2.toSet)).toSet === expected)
94+ sorter3.stop()
8895
8996 // Neither aggregator nor ordering
9097 val sorter4 = new ExternalSorter [Int , Int , Int ](
9198 None , Some (new HashPartitioner (7 )), None , None )
9299 sorter4.write(elements.iterator)
93100 assert(sorter4.partitionedIterator.map(p => (p._1, p._2.toSet)).toSet === expected)
101+ sorter4.stop()
102+ }
103+
104+ test(" empty partitions with spilling" ) {
105+ val conf = new SparkConf (false )
106+ conf.set(" spark.shuffle.memoryFraction" , " 0.001" )
107+ conf.set(" spark.shuffle.manager" , " org.apache.spark.shuffle.sort.SortShuffleManager" )
108+ sc = new SparkContext (" local" , " test" , conf)
109+
110+ val agg = new Aggregator [Int , Int , Int ](i => i, (i, j) => i + j, (i, j) => i + j)
111+ val ord = implicitly[Ordering [Int ]]
112+ val elements = Iterator ((1 , 1 ), (5 , 5 )) ++ (0 until 50000 ).iterator.map(x => (2 , 2 ))
113+
114+ val sorter = new ExternalSorter [Int , Int , Int ](
115+ None , Some (new HashPartitioner (7 )), None , None )
116+ sorter.write(elements)
117+ assert(sc.env.blockManager.diskBlockManager.getAllFiles().length > 0 ) // Make sure it spilled
118+ val iter = sorter.partitionedIterator.map(p => (p._1, p._2.toList))
119+ assert(iter.next() === (0 , Nil ))
120+ assert(iter.next() === (1 , List ((1 , 1 ))))
121+ assert(iter.next() === (2 , (0 until 50000 ).map(x => (2 , 2 )).toList))
122+ assert(iter.next() === (3 , Nil ))
123+ assert(iter.next() === (4 , Nil ))
124+ assert(iter.next() === (5 , List ((5 , 5 ))))
125+ assert(iter.next() === (6 , Nil ))
126+ sorter.stop()
94127 }
95128
96129 test(" spilling in local cluster" ) {
0 commit comments