FAQ
Hi,

I have some strange behaviour in channels that has become apparent whilst
running the unit tests.

I have struct - UrlState
type UrlState struct {
Url string
ResponseStatus string
ResponseCode int
Attempted time.Time
AttemptCount int
}

Then 2 channels pending and done which are channels of *data.UrlState

In my controller code I have a function that moves data between the
channels. Son when an item in pending is proccessed it is moved to done.
Once pending is empty I will move everything back to done, that at least is
the end game. Right now I am just trying to test the move code:

type QueueManager struct {
}

func (qm *QueueManager) MoveBetweenChannels(source, target chan
*data.UrlState) int {
var moving sync.WaitGroup
moved := 0
for urlState := range source {
moving.Add(1)
go func() {
target <- urlState
moved++
moving.Done()
}()
}
moving.Wait()
close(target)
return moved
}

I am testing this from a unit test:

package controller

import (
"data"
"fmt"
"testing"
"time"
)

var qm *QueueManager
var pending chan *data.UrlState
var done chan *data.UrlState
var expectedCount int

var urls = []string{
"http://www.naver.com",
"http://www.bbc.co.uk",
"http://www.slashdot.com",
"http://www.guardian.co.uk",
"http://www.yahoo.co.uk",
"http://www.stackoverflow.com",
}

func setUpFortest() {
qm = new(QueueManager)
expectedCount = len(urls)
done = make(chan *data.UrlState)
pending = make(chan *data.UrlState)
go func() {
for _, url := range urls {
state := new(data.UrlState)
state.Url = url
state.ResponseStatus = ""
state.ResponseCode = 0
state.Attempted = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
state.AttemptCount = 0
pending <- state
}
close(pending)
}()
}

func TestQueueMove(t *testing.T) {
setUpFortest()
moved := 0
go func() {
moved = qm.MoveBetweenChannels(pending, done) // this move is for the test,
wouldn't normally move in this direction
}()
for urlState := range pending {
fmt.Printf("Pending M URL: %s\n", urlState.Url)
}
for urlState := range done {
fmt.Printf("done URL: %s\n", urlState.Url)
}
/*if moved != expectedCount {
t.Errorf("Unexpected moved result. Expected %d; got %d", expectedCount,
moved)
}*/
}

As you can see I am clearly struggling with this I have lots of fmt.Printf
in place. What I would expect is that the 6 items in the pending channel
are moved to the done channel (running this way for ease of test). This
owuld then give me the URLs in the slice on done and the number of moved
items equal to 6.

However, the result I get is: (from the fmt lines)
Pending M URL: http://www.naver.com
Pending M URL: http://www.guardian.co.uk
done URL: http://www.bbc.co.uk
done URL: http://www.yahoo.co.uk
done URL: http://www.yahoo.co.uk
done URL: http://www.stackoverflow.com
With only 4 items moved not 6 as expected.

I am drawing a blank on why this might be happening. I thin k perhaps I
don't have a concrete grasp on channels yet.

Can some please explain to me why this is happening? I feel that if I can
get this cracked it will really help me to make sure this small app I am
building is correct. This will, in turn, help to showcase what Go can do.

Thanks
Nathan



--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Search Discussions

  • Minux at Dec 9, 2013 at 5:42 pm

    On Dec 9, 2013 12:22 PM, wrote:
    Hi,

    I have some strange behaviour in channels that has become apparent whilst
    running the unit tests.
    I have struct - UrlState
    type UrlState struct {
    Url string
    ResponseStatus string
    ResponseCode int
    Attempted time.Time
    AttemptCount int
    }

    Then 2 channels pending and done which are channels of *data.UrlState

    In my controller code I have a function that moves data between the
    channels. Son when an item in pending is proccessed it is moved to done.
    Once pending is empty I will move everything back to done, that at least is
    the end game. Right now I am just trying to test the move code:
    type QueueManager struct {
    }

    func (qm *QueueManager) MoveBetweenChannels(source, target chan
    *data.UrlState) int {
    var moving sync.WaitGroup
    moved := 0
    for urlState := range source {
    moving.Add(1)
    go func() {
    target <- urlState
    moved++
    moving.Done()
    }()
    }
    moving.Wait()
    close(target)
    return moved
    }

    I am testing this from a unit test:

    package controller

    import (
    "data"
    "fmt"
    "testing"
    "time"
    )

    var qm *QueueManager
    var pending chan *data.UrlState
    var done chan *data.UrlState
    var expectedCount int

    var urls = []string{
    "http://www.naver.com",
    "http://www.bbc.co.uk",
    "http://www.slashdot.com",
    "http://www.guardian.co.uk",
    "http://www.yahoo.co.uk",
    "http://www.stackoverflow.com",
    }

    func setUpFortest() {
    qm = new(QueueManager)
    expectedCount = len(urls)
    done = make(chan *data.UrlState)
    pending = make(chan *data.UrlState)
    go func() {
    for _, url := range urls {
    state := new(data.UrlState)
    state.Url = url
    state.ResponseStatus = ""
    state.ResponseCode = 0
    state.Attempted = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
    state.AttemptCount = 0
    pending <- state
    }
    close(pending)
    }()
    }

    func TestQueueMove(t *testing.T) {
    setUpFortest()
    moved := 0
    go func() {
    moved = qm.MoveBetweenChannels(pending, done) // this move is for the
    test, wouldn't normally move in this direction
    }()
    for urlState := range pending {
    fmt.Printf("Pending M URL: %s\n", urlState.Url)
    }
    you have two goroutines receiving from the same channel (pending), without
    synchronization.
    for urlState := range done {
    fmt.Printf("done URL: %s\n", urlState.Url)
    }
    /*if moved != expectedCount {
    t.Errorf("Unexpected moved result. Expected %d; got %d", expectedCount, moved)
    }*/
    }

    As you can see I am clearly struggling with this I have lots of
    fmt.Printf in place. What I would expect is that the 6 items in the pending
    channel are moved to the done channel (running this way for ease of test).
    This owuld then give me the URLs in the slice on done and the number of
    moved items equal to 6.
    However, the result I get is: (from the fmt lines)
    Pending M URL: http://www.naver.com
    Pending M URL: http://www.guardian.co.uk
    done URL: http://www.bbc.co.uk
    done URL: http://www.yahoo.co.uk
    done URL: http://www.yahoo.co.uk
    done URL: http://www.stackoverflow.com
    With only 4 items moved not 6 as expected.

    I am drawing a blank on why this might be happening. I thin k perhaps I
    don't have a concrete grasp on channels yet.
    Can some please explain to me why this is happening? I feel that if I can
    get this cracked it will really help me to make sure this small app I am
    building is correct. This will, in turn, help to showcase what Go can do.
    Thanks
    Nathan



    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Dmitry Vyukov at Dec 9, 2013 at 5:42 pm
    Run the code under race detector.

    On Mon, Dec 9, 2013 at 9:22 PM, wrote:
    Hi,

    I have some strange behaviour in channels that has become apparent whilst
    running the unit tests.

    I have struct - UrlState
    type UrlState struct {
    Url string
    ResponseStatus string
    ResponseCode int
    Attempted time.Time
    AttemptCount int
    }

    Then 2 channels pending and done which are channels of *data.UrlState

    In my controller code I have a function that moves data between the
    channels. Son when an item in pending is proccessed it is moved to done.
    Once pending is empty I will move everything back to done, that at least is
    the end game. Right now I am just trying to test the move code:

    type QueueManager struct {
    }

    func (qm *QueueManager) MoveBetweenChannels(source, target chan
    *data.UrlState) int {
    var moving sync.WaitGroup
    moved := 0
    for urlState := range source {
    moving.Add(1)
    go func() {
    target <- urlState
    moved++
    moving.Done()
    }()
    }
    moving.Wait()
    close(target)
    return moved
    }

    I am testing this from a unit test:

    package controller

    import (
    "data"
    "fmt"
    "testing"
    "time"
    )

    var qm *QueueManager
    var pending chan *data.UrlState
    var done chan *data.UrlState
    var expectedCount int

    var urls = []string{
    "http://www.naver.com",
    "http://www.bbc.co.uk",
    "http://www.slashdot.com",
    "http://www.guardian.co.uk",
    "http://www.yahoo.co.uk",
    "http://www.stackoverflow.com",
    }

    func setUpFortest() {
    qm = new(QueueManager)
    expectedCount = len(urls)
    done = make(chan *data.UrlState)
    pending = make(chan *data.UrlState)
    go func() {
    for _, url := range urls {
    state := new(data.UrlState)
    state.Url = url
    state.ResponseStatus = ""
    state.ResponseCode = 0
    state.Attempted = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
    state.AttemptCount = 0
    pending <- state
    }
    close(pending)
    }()
    }

    func TestQueueMove(t *testing.T) {
    setUpFortest()
    moved := 0
    go func() {
    moved = qm.MoveBetweenChannels(pending, done) // this move is for the test,
    wouldn't normally move in this direction
    }()
    for urlState := range pending {
    fmt.Printf("Pending M URL: %s\n", urlState.Url)
    }
    for urlState := range done {
    fmt.Printf("done URL: %s\n", urlState.Url)
    }
    /*if moved != expectedCount {
    t.Errorf("Unexpected moved result. Expected %d; got %d", expectedCount,
    moved)
    }*/
    }

    As you can see I am clearly struggling with this I have lots of fmt.Printf
    in place. What I would expect is that the 6 items in the pending channel are
    moved to the done channel (running this way for ease of test). This owuld
    then give me the URLs in the slice on done and the number of moved items
    equal to 6.

    However, the result I get is: (from the fmt lines)
    Pending M URL: http://www.naver.com
    Pending M URL: http://www.guardian.co.uk
    done URL: http://www.bbc.co.uk
    done URL: http://www.yahoo.co.uk
    done URL: http://www.yahoo.co.uk
    done URL: http://www.stackoverflow.com
    With only 4 items moved not 6 as expected.

    I am drawing a blank on why this might be happening. I thin k perhaps I
    don't have a concrete grasp on channels yet.

    Can some please explain to me why this is happening? I feel that if I can
    get this cracked it will really help me to make sure this small app I am
    building is correct. This will, in turn, help to showcase what Go can do.

    Thanks
    Nathan



    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.
  • Ndavies at Dec 28, 2013 at 8:26 am
    Hi,

    Thanks for the input and sorry for the delayed response; I got caught up in
    some other project work and had to put this to one side. I will get back to
    this in January and will look at both suggestions, making sure I have the
    use of the channels correct and then running the race detector. I'll let
    you know how I get on.

    I hope you are enjoying the Christmas season and I wish you the very best
    for 2014.
    Nathan
    On Monday, December 9, 2013 5:42:20 PM UTC, Dmitry Vyukov wrote:

    Run the code under race detector.


    On Mon, Dec 9, 2013 at 9:22 PM, <nda...@iparadigms.com <javascript:>>
    wrote:
    Hi,

    I have some strange behaviour in channels that has become apparent whilst
    running the unit tests.

    I have struct - UrlState
    type UrlState struct {
    Url string
    ResponseStatus string
    ResponseCode int
    Attempted time.Time
    AttemptCount int
    }

    Then 2 channels pending and done which are channels of *data.UrlState

    In my controller code I have a function that moves data between the
    channels. Son when an item in pending is proccessed it is moved to done.
    Once pending is empty I will move everything back to done, that at least is
    the end game. Right now I am just trying to test the move code:

    type QueueManager struct {
    }

    func (qm *QueueManager) MoveBetweenChannels(source, target chan
    *data.UrlState) int {
    var moving sync.WaitGroup
    moved := 0
    for urlState := range source {
    moving.Add(1)
    go func() {
    target <- urlState
    moved++
    moving.Done()
    }()
    }
    moving.Wait()
    close(target)
    return moved
    }

    I am testing this from a unit test:

    package controller

    import (
    "data"
    "fmt"
    "testing"
    "time"
    )

    var qm *QueueManager
    var pending chan *data.UrlState
    var done chan *data.UrlState
    var expectedCount int

    var urls = []string{
    "http://www.naver.com",
    "http://www.bbc.co.uk",
    "http://www.slashdot.com",
    "http://www.guardian.co.uk",
    "http://www.yahoo.co.uk",
    "http://www.stackoverflow.com",
    }

    func setUpFortest() {
    qm = new(QueueManager)
    expectedCount = len(urls)
    done = make(chan *data.UrlState)
    pending = make(chan *data.UrlState)
    go func() {
    for _, url := range urls {
    state := new(data.UrlState)
    state.Url = url
    state.ResponseStatus = ""
    state.ResponseCode = 0
    state.Attempted = time.Date(2009, time.November, 10, 23, 0, 0, 0, time.UTC)
    state.AttemptCount = 0
    pending <- state
    }
    close(pending)
    }()
    }

    func TestQueueMove(t *testing.T) {
    setUpFortest()
    moved := 0
    go func() {
    moved = qm.MoveBetweenChannels(pending, done) // this move is for the test,
    wouldn't normally move in this direction
    }()
    for urlState := range pending {
    fmt.Printf("Pending M URL: %s\n", urlState.Url)
    }
    for urlState := range done {
    fmt.Printf("done URL: %s\n", urlState.Url)
    }
    /*if moved != expectedCount {
    t.Errorf("Unexpected moved result. Expected %d; got %d", expectedCount,
    moved)
    }*/
    }

    As you can see I am clearly struggling with this I have lots of
    fmt.Printf
    in place. What I would expect is that the 6 items in the pending channel are
    moved to the done channel (running this way for ease of test). This owuld
    then give me the URLs in the slice on done and the number of moved items
    equal to 6.

    However, the result I get is: (from the fmt lines)
    Pending M URL: http://www.naver.com
    Pending M URL: http://www.guardian.co.uk
    done URL: http://www.bbc.co.uk
    done URL: http://www.yahoo.co.uk
    done URL: http://www.yahoo.co.uk
    done URL: http://www.stackoverflow.com
    With only 4 items moved not 6 as expected.

    I am drawing a blank on why this might be happening. I thin k perhaps I
    don't have a concrete grasp on channels yet.

    Can some please explain to me why this is happening? I feel that if I can
    get this cracked it will really help me to make sure this small app I am
    building is correct. This will, in turn, help to showcase what Go can do.
    Thanks
    Nathan



    --
    You received this message because you are subscribed to the Google Groups
    "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an
    email to golang-nuts...@googlegroups.com <javascript:>.
    For more options, visit https://groups.google.com/groups/opt_out.
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/groups/opt_out.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedDec 9, '13 at 5:22p
activeDec 28, '13 at 8:26a
posts4
users3
websitegolang.org

3 users in discussion

Ndavies: 2 posts Dmitry Vyukov: 1 post Minux: 1 post

People

Translate

site design / logo © 2022 Grokbase